Switch AI agent to Third Person View: Error after first switch

willquon

New member
Hi,

first of all I really like your product and you are doing a fantastic job.

However, I have a problem with the UCC. I am creating a real time strategy game as a University project where the player can switch into Third Person View for one of the characters.

Therefore, I have set up a Third person character which can be controlled by the user. Then I have added all the components that are needed to control the character if the player is in RTS perspective. I am using the Unity NavMesh and have therefore added the NavMeshMovement ability as well.
I have a script which controls the activation/deactivation of the components of the character and also the camera.

Everything is fine so far. The switching works fine but just the first time, which means the player starts in RTS view, selects the character to switch into, switches into TPV. Then he can also switch back to RTS view. But if he tries to switch into the character a second time following error appears:
NullReferenceException: Object reference not set to an instance of an object
Opsive.UltimateCharacterController.ThirdPersonController.Character.MovementTypes.Combat.GetDeltaYawRotation (Single characterHorizontalMovement, Single characterForwardMovement, Single cameraHorizontalMovement, Single cameraVerticalMovement) (at Assets/Opsive/UltimateCharacterController/Scripts/ThirdPersonController/Character/MovementTypes/Combat.cs:28)
Opsive.UltimateCharacterController.Character.UltimateCharacterLocomotionHandler.GetDeltaYawRotation () (at Assets/Opsive/UltimateCharacterController/Scripts/Character/UltimateCharacterLocomotionHandler.cs:196)
Opsive.UltimateCharacterController.Game.KinematicObjectManager+KinematicCharacter.FixedMove () (at Assets/Opsive/UltimateCharacterController/Scripts/Game/KinematicObjectManager.cs:179)
Opsive.UltimateCharacterController.Game.KinematicObjectManager.FixedUpdate () (at Assets/Opsive/UltimateCharacterController/Scripts/Game/KinematicObjectManager.cs:703)

I tried a lot of things but I have no idea how to fix it because it works the first time...
I would appreciate any help :)

Here is the script that toggles the components on and off:
C#:
public class RTStoTPVHandler : MonoBehaviour {

    GameManager gameManager; //My own game manager script
    
    UltimateCharacterLocomotion charLoco;
    UltimateCharacterLocomotionHandler charLocoHandler;
    UnityInput unityInput;
    NavMeshAgent navMeshAgent;

    CameraController cameraController;
    CameraControllerHandler cameraControllerHandler;
    ObjectFader objectFader;

    RTS_Camera rtsCam; //My RTS camera script
    TargetSelector targetSelector;//Part of the RTS camera

    LocalLookSource lookSource;

    MoveToClickPoint moveToClickPoint;

    GameObject tpvUI;

    GameObject rtsUI;

    Vector3 camAngle;
    bool runOnce = true;

    bool inTPV = false;

    // Use this for initialization
    void Start () {
        gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
        charLoco = GetComponent<UltimateCharacterLocomotion>();
        charLocoHandler = GetComponent<UltimateCharacterLocomotionHandler>();
        unityInput = GetComponent<UnityInput>();
        navMeshAgent = GetComponent<NavMeshAgent>();
        lookSource = GetComponent<LocalLookSource>();

        cameraController = Camera.main.GetComponent<CameraController>();
        cameraControllerHandler = Camera.main.GetComponent<CameraControllerHandler>();
        objectFader = Camera.main.GetComponent<ObjectFader>();

        rtsCam = Camera.main.GetComponent<RTS_Camera>();
        targetSelector = Camera.main.GetComponent<TargetSelector>();

        moveToClickPoint = GetComponent<MoveToClickPoint>();

        tpvUI = GameObject.Find("Monitors");
        rtsUI = GameObject.Find("CharacterUI");

        tpvUI.SetActive(false);

        EventHandler.ExecuteEvent(gameObject, "OnEnableGameplayInput", false);
        if (runOnce)
        {
            Debug.Log("NavMeshAB STARTED");
            charLoco.TryStartAbility(charLoco.GetAbility<NavMeshAgentMovement>());
            runOnce = false;
        }
        

        camAngle = new Vector3(60f, 0f, 0f);
    }
    
    public void changeView()
    {
        var navMeshAbility = charLoco.GetAbility<NavMeshAgentMovement>();
        
        
            gameObject.tag = "Player";

            lookSource.enabled = false;           

            charLoco.TryStopAbility(navMeshAbility);
            moveToClickPoint.enabled = false;

            rtsCam.enabled = false;
            targetSelector.enabled = false;
            Debug.Log("Cam0 DONE");

            //change Cam components
            cameraController.enabled = true;
            if (cameraController.Character != gameObject)
            {
                cameraController.Character = gameObject;
            }
            cameraControllerHandler.enabled = true;

            EventHandler.ExecuteEvent(gameObject, "OnEnableGameplayInput", true);

            
            tpvUI.SetActive(true);
            rtsUI.SetActive(false);
            gameManager.inTPV = true;
            inTPV = true;
        
    }

    private void Update()
    {
        if (inTPV)
        {
            if(Input.GetButtonDown("Toggle Perspective"))
            {
                var navMeshAbility = charLoco.GetAbility<NavMeshAgentMovement>();
                unityInput.DisableCursor = false;
                EventHandler.ExecuteEvent(gameObject, "OnEnableGameplayInput", false);

                cameraController.enabled = false;
                cameraControllerHandler.enabled = false;

                rtsCam.enabled = true;
                targetSelector.enabled = true;

                lookSource.enabled = true;

                navMeshAgent.destination = transform.position;
                charLoco.TryStartAbility(navMeshAbility);
                Debug.Log("NavMeshAB STARTED 1");
                moveToClickPoint.enabled = true;
                gameObject.tag = "Unit";

                Camera.main.transform.eulerAngles = camAngle;

                tpvUI.SetActive(false);
                rtsUI.SetActive(true);
                gameManager.inTPV = false;
                inTPV = false;
            }
        }
    }
}

Best,
Florian
 
Instead of disabling the camera controller you should create a new view type that uses your RTS camera. Take a look at the cinmeachine integration for an example - this view type moves the camera based on the cinemachine camera controller and it doesn't disable the UCC camera controller.
 
Alright, I will have a look on it. If I have the ViewType created and assigned, how can I switch between the camera view types from a script? I somehow cant figure that out.
 
I literally just discovered it :D
I was first a bit confused because in the docs it says cameraController.SwitchViewType() but it is SetViewType, as you just said.
 
However, when I switch from my RTS view back into TP combat the mouse doesn't control the cam and character anymore...
 
I guess this is because of the Local look source. If I just dissable the component I get an Error, but I cannot reset it because it is read only.
 
Not sure anymore if that is related to the local look source. If I disable it completely from the start and not change it, I dont get an error but the mouse axis are still not discovered. I think it has to do something with the Input...
 
This is tough to debug since it is a lot of custom code but the look source will be set when you assign the character. The look source should only be assigned once and it doesn't change when you change the view type.

Just as a test I would create a clean project and create a minimal view type. You won't need most of the code within RTStoTPVHandler and can switch view types using SetViewType. From here you can slowly build on top of it and then once you get that working you'll have something to compare against in your main project.
 
Top