Search Unity

  1. Calling all beginners! Join the FPS Beginners Mods Challenge until December 13.
    Dismiss Notice
  2. It's Cyber Week at the Asset Store!
    Dismiss Notice

Character Controller ignores transform.position

Discussion in 'Scripting' started by EnriqueGato, Jan 22, 2019.

  1. EnriqueGato

    EnriqueGato

    Joined:
    Sep 3, 2016
    Posts:
    51
    I had to re-import my project in a new, clean one and, after doing this, I'm having a weird behaviour from Character Controller component.

    If I do this:
    Code (CSharp):
    1. transform.position = newPosition;  // place the character in Checkpoint's position
    2. characterController.Move(velocity);  // move the character
    The character controller ignores the new position and moves the character from the previous one.

    Anyone knows why this happened? It worked right before re-importing the project.
     
  2. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    4,380
    The character controller has it's own internal definition of what position it has, and will set the transform's position to that every frame, so you can't move it with transform.position.

    For some reason, there's no .Warp method (like there's on NavMeshAgents that have the same issue). I seem to remember that you can do this, though:

    Code (csharp):
    1.  //probably extract this into a helper method.
    2. characterController.enabled = false;
    3. characterController.transform.position = pos;
    4. characterController.enabled = true;
    As I (believe) that the character controller checks it's starting position in OnEnable.
     
    GamingFriendsCZ likes this.
  3. MonkeyZero

    MonkeyZero

    Joined:
    Feb 20, 2013
    Posts:
    36
    This issue gets even worse. Even with the fix @Baste suggest, This really only fixes the position. Rotation, on the other hand, is still ignored completely even when wrapping it in the enabled switches.

    How do we fix.
    Code (CSharp):
    1. characterController.transform.rotation = rot;
     
  4. MonkeyZero

    MonkeyZero

    Joined:
    Feb 20, 2013
    Posts:
    36
    I realized I got a bit harsh and was reposting to change the tone and did it again. One sec.

    Okay first, Yeah it used to work directly. For some reason, the character controller component was changed. It no longer respects this at all as of 2018.2 or so.

    I have a Spawn Marker system in mind that acts as a target for the player controller to use as a refrence when starting a level or traveling between two scenes. Think Fallout 3+ or the Elder Scrolls Oblivion/Skyrim.

    Here is my code exacly at this moment.

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class SpawnTarget : MonoBehaviour
    7. {
    8.     public string TargetSpawn = "SpawnName";
    9.     public string TargetScene = "SceneName";
    10.  
    11.     public void SetSpawnTarget(string _spawn)
    12.     {
    13.         TargetSpawn = _spawn;
    14.         Debug.Log("Player's SpawnTarget is now set to: " + TargetSpawn);
    15.     }
    16.  
    17.     public void SetSceneTarget(string _scene)
    18.     {
    19.         TargetScene = _scene;
    20.         Debug.Log("Player's SceneTarget is now set to: " + TargetScene);
    21.     }
    22. }
    This code sits on the Player Controller which is a modified version of the Standard Assets First Person Controller that removes CrossPlatformInput dependency.

    This character Controller is Presisitent by being a child of the Game Mananger Singleton I've created out of an Event Mananger.

    The second Part goes onto the Spawn marker itself.
    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class SpawnMarker : MonoBehaviour
    7. {
    8.     public string MarkerAddress = "SpawnName";
    9.     public string PlayerTag = "Player";
    10.  
    11.     [SerializeField] private GameObject m_player;
    12.    
    13.     void Start()
    14.     {
    15.         m_player = GameObject.FindGameObjectWithTag(PlayerTag);
    16.  
    17.         if (m_player.GetComponent<SpawnTarget>().TargetSpawn == MarkerAddress)
    18.         {
    19.             m_player.GetComponent<CharacterController>().enabled = false;
    20.             m_player.GetComponent<Player.FirstPerson.FirstPersonController>().enabled = false;
    21.  
    22.             m_player.transform.position = this.transform.position;
    23.             m_player.transform.rotation = this.transform.rotation;
    24.  
    25.             m_player.GetComponent<CharacterController>().enabled = true;
    26.             m_player.GetComponent<Player.FirstPerson.FirstPersonController>().enabled = true;
    27.  
    28.             Debug.Log("The Player should not be at: " + this.transform.position + " position and rotated to: " + this.transform.rotation);
    29.             Debug.Log("If this is not the case then something has really gone wrong...");
    30.         }
    31.     }
    32. }
    This is a Scene Object that can be placed and rotated anywhere in the scene and when the scene gets loaded up and started, looks for the Player Controller by tag and is supposed to move it to itself and then rotate the player controller to match.

    The code works becuase it moves a cubes with the Spawn Targets script attached and tagged as player just fine. It even rotates it correctly not an issue. But when the CharacterController Capsule is attached, It looses all respect for the position and rotation. It's as if it never happened.

    The position can be fixed by turning off the CharacterController Component while the move is being made, but rotation is still ignored.

    Your game must be using an older version of unity becuase this is a fairly new issue.

    I've used this method before for a while with out issue untill a couble of version ago.
     
  5. Valthec

    Valthec

    Joined:
    Jul 10, 2017
    Posts:
    2
    I had similar issue with a script that moves player to Scene's zero position. When CharacterController script was active I couldn't move player even in the editor play mode. I was able to solve it by change Edit>>Project Settings>>Physics>>Auto Sync Transform set to True. After that I was able to drag my player object in play mode.

    Here is the fix source and explanation: https://issuetracker.unity3d.com/is...-when-teleporting-with-transform-dot-position
     
  6. GamingFriendsCZ

    GamingFriendsCZ

    Joined:
    Mar 1, 2017
    Posts:
    2
    Ty sir
     
  7. ishwara_bhat

    ishwara_bhat

    Joined:
    Oct 18, 2018
    Posts:
    11
    Thanks Baste.
    I just added rotation. Also added bit more code on getting the rotation

    //Unity call of instantiation
    char = OnInstantiate(..)
    char.GetComponent<CharacterController>().enabled = false;
    char.transform.position = newPosition.position;
    char.transform.rotation = newPosition.rotation;
    char.GetComponent<CharacterController>().enabled = true;
     
  8. Vharz

    Vharz

    Joined:
    Jul 28, 2012
    Posts:
    7
    I solved it by doing a custom "Warp" method with characterController.Move(Vector3.zero) just before setting it's position/rotation.

    After the "warp" it just continues to pick up regular Move() input from Update().