How do you aim rifles using virtual controls (equivalent of right mouse)

mrblasto

New member
In the standalone first person perspective of the demo, you can aim the rifles using the right mouse button. I'm trying to do the same, mapping the action button (or any button) to a method that aims (brings up scope view) and un-aims the rifle (return to normal view). I've found the aim ability but I'm not sure what I need to do to actually perform an aim. Any help or pointers would be appreciated.
 
First, I found that the mapping for aim is Fire2, not Fire3. Fire3 appears to have no action. When I put Fire2 in the Button Name field of the VirtualButton component it worked but it ate the pointer. Basically it stopped responding to touch input. Fire1 works perfectly (it shoots the weapon). While pressed Fire2 performs the aim, but no other touch input (or mouse if in editor) is possible. Releasing Fire2 restores to normal, but again no touch input. I suspect it's because Attack is an ability and Aim is an item ability but I don't know how to get the touch back.

I tried the manual start. The jump example worked, but when I substituted the aim ItemAbility it didn't. Again I think it has to do with the fact that an item ability has to be handled differently than a plain ability. The code I tried is shown below. The code is getting called but it doesn't do anything. Please advise or provide a specific example.

Code:
using UnityEngine;
using Opsive.UltimateCharacterController.Character;
using Opsive.UltimateCharacterController.Character.Abilities.Items;

public class Aimer : MonoBehaviour {

    [Tooltip("The character that should start and stop the aim ability.")]
    [SerializeField] protected GameObject m_Character;

    bool m_isAiming = false;
    UltimateCharacterLocomotion m_characterLocomotion;
    ItemAbility m_aimAbility;

    private void Start()
    {
        m_isAiming = false;
        m_characterLocomotion = m_Character.GetComponent<UltimateCharacterLocomotion>();
        m_aimAbility = m_characterLocomotion.GetAbility<Aim>();
    }

    /// <summary>
    /// Starts and stops the aim ability.
    /// </summary>
    public void Aim()
    {
        if (!m_isAiming)
        {
            m_characterLocomotion.TryStartAbility(m_aimAbility);
            Debug.Log("aim ability started");
            m_isAiming = true;
        }
        // Stop the jump ability if it is active.
        else
        {
            Debug.Log("aim ability stopped");
            m_characterLocomotion.TryStopAbility(m_aimAbility);
            m_isAiming = false;
        }
    }
}
 
Oops, you're right, it is Fire2. Item Abilities are started the same as regular abilities - if you place a breakpoint when you call TryStartAbility does the ability start?
 
No, it will only start if I call it from the Fire2. I traced the call from Fire2 -- I can walk thru the entire code path until the next step over changes from pause to play. Then when I click on the game window, the aim takes effect. How about approaching this a different way. Why does invoking Fire2 disable touch/mouse input but Fire1 doesn't? I'd settle for a simple script example that works -- toggle a button on, it aims, toggle it off, it turns off aim. Another alternative is some insight into which animation parameters to tweak or where the actual code is that causes the action -- there's so many levels of tries here it's difficult to figure out what's happening where. Getting to the end of the path and then finding that the change only occurs when I click on the game window (and then immediately losing the mouse) is so frustrating.

Just thought of a simple repro case -- in the demo scene map one of the virtual buttons to Fire2. Press it. Note the mouse disappears and the game no longer receives input events even if you press ESC to get the mouse cursor back.
 
Last edited:
What I think is happening is that the aim ability is starting, but it is stopping right away. It is being stopped because by default the Ability Stop Type is set to Button Up. Since the Fire2 button is up, the ability then stops. If you set the ability start/stop type to manual then it will be completely controlled by your script.

The cursor disappears when you press on the window because of the Unity Input component - you can deselect Disable Cursor and the cursor will no longer be disabled.
 
The solution in the first paragraph didn't work for but the second, unselecting Disable Cursor, did work. I tried slowing down time to 1/10th and I didn't see an aim effect so I'm not convinced it ever started when trying to control it manually. I set both the AbilityStartType and AbilityStopType to Manual. I'd like to be able to start and stop manually, but for now I've got a workable solution by turning off disable cursor in Unity.Input.

Here's the method I use to manually toggle aim (m_isAiming is initialized to false in Start()).

C#:
    public void Aim()
    {
        m_characterLocomotion = m_Character.GetComponent<UltimateCharacterLocomotion>();
        m_aimAbility = m_characterLocomotion.GetAbility<Aim>();
        m_aimAbility.StartType = ItemAbility.AbilityStartType.Manual;
        m_aimAbility.StopType = ItemAbility.AbilityStopType.Manual;
        m_aimAbility.Start();
        if (!m_isAiming)
        {
            m_characterLocomotion.TryStartAbility(m_aimAbility);
            Debug.Log("aim ability started");
            m_isAiming = true;
        }
        // Stop the jump ability if it is active.
        else
        {
            Debug.Log("aim ability stopped");
            m_characterLocomotion.TryStopAbility(m_aimAbility);
            m_isAiming = false;
        }
    }
 
When I tested this I used:

Code:
using UnityEngine;
using Opsive.UltimateCharacterController.Character;
using Opsive.UltimateCharacterController.Character.Abilities.Items;

public class AimTest : MonoBehaviour {

    public GameObject m_Character;

    // Use this for initialization
    void Start () {
        Invoke("StartAim", 2);
    }
   
    void StartAim()
    {
        var aim = m_Character.GetComponent<UltimateCharacterLocomotion>().GetAbility<Aim>();
        m_Character.GetComponent<UltimateCharacterLocomotion>().TryStartAbility(aim);
    }
}

You don't want to call Aim.Start manually as the controller will call it at the right time. If the ability isn't starting you can see what is blocking it by placing a breakpoint within TryStartAbility.
 
Top