1
\$\begingroup\$

I have a character controller to move my player on a surface. All the things work fine, but I can't make a perfect slide with the character controller on the surface.

When I try to slide, my player animation plays in the center of capsule collider, which is attached to the player. That's why my player can not touch floor, which means my animation play in mid air. After some time I found that my problem occurs due to using the character controller. I am using Character.Move() to move my player.

Can anyone help me? How can I avoid the collider on the character controller, or change something to make my player slide animation perfectly align with the floor.?

I am using controller.transform.Rotate(0,0,60) to rotate my player on floor.

This is my script:

using UnityEngine;
using Assets.Scripts;
using System.Collections;
using UnityEngine.SceneManagement;

public class ControllerMovement : MonoBehaviour {

private Vector3 moveDirection = Vector3.zero;
public float gravity = 20f;
private CharacterController controller;
public float JumpSpeed = 8.0f;
public float Speed = 0.1f;
public int swipeStep = 3;
int swipeD,pos;
bool rx ;
int i=0;
public Transform CharacterGO;
bool isInSwipeArea;
private Animator anim;
IInputDetector inputDetector = null;

// Use this for initialization

void Start()
{
    moveDirection = transform.forward;
    moveDirection = transform.TransformDirection(moveDirection);
    moveDirection *= Speed;
    UIManager.Instance.ResetScore();
    UIManager.Instance.SetStatus(Constants.StatusTapToStart);
    GameManager.Instance.GameState = GameState.Start;

    anim = CharacterGO.GetComponentInChildren<Animator> ();
    inputDetector = GetComponent<IInputDetector>();
    controller = GetComponent<CharacterController>();   
}

// Update is called once per frame
void Update()
{
    switch (GameManager.Instance.GameState)
    {
    case GameState.Start:
        if (Input.GetMouseButtonUp(0))
        {
            //anim.SetBool(Constants.animaationStarted, true);
            var instance = GameManager.Instance;
            instance.GameState = GameState.Playing;
            UIManager.Instance.SetStatus(string.Empty);
        }
        break;
    case GameState.Playing:
        UIManager.Instance.IncreaseScore (0.001f);
        CheckHeight ();
        DetectJumpOrSwipeLeftRight ();


        //apply gravity
        moveDirection.y -= gravity * Time.deltaTime;
        //move the player
        controller.Move (moveDirection * Time.deltaTime);
        break;

    case GameState.Dead:
        ////anima.SetBool(Constants.//animaationStarted, false);
        if (Input.GetMouseButtonUp(0))
        {         SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
        }
        break;
    default:
        break;
    }
}
private void CheckHeight()
{
    if (transform.position.y < -10)
    {
        GameManager.Instance.Die();
    }
}

private void DetectJumpOrSwipeLeftRight()
{
    var inputDirection = inputDetector.DetectInputDirection();

    if (Input.GetKeyDown (KeyCode.Space)) {
        moveDirection.y = JumpSpeed;
        anim.SetBool ("RunToJump", true);
    } else {
        anim.SetBool ("RunToJump", false);
    }
    if(Input.GetKey(KeyCode.A) && controller.isGrounded){
        controller.transform.Translate (-0.1f,0,0);         
    }
    if(Input.GetKey(KeyCode.D) && controller.isGrounded){
        controller.transform.Translate (0.1f,0,0);          
    }
    if (Input.GetKey (KeyCode.S) && controller.isGrounded) {                                    
        anim.SetBool ("RunToSlip", true);
        controller.transform.Rotate (-40, 0, 0);
        Invoke ("StopSlidding", 0.2f);
    } 
        }
 void StopSlidding(){       
    anim.SetBool ("RunToSlip", false);
    controller.transform.Rotate (40,0,0);

  }

 }
\$\endgroup\$
  • \$\begingroup\$ Do you have both animator and character controller in one object or you maintained a parent child hierarchy? \$\endgroup\$ – Sourav Paul Aug 19 '16 at 6:13
  • \$\begingroup\$ Yes, I have both in single object. @SP. \$\endgroup\$ – hardwork Aug 19 '16 at 6:15
  • \$\begingroup\$ It should be anim = GetComponentInChildren<Animator> (); if the character object is as child. This has noting to do with parent rotation. You should usually rotate parent object not trying with ChracterController. \$\endgroup\$ – Sourav Paul Aug 19 '16 at 7:24
  • \$\begingroup\$ still sucking same problem.. @SP. \$\endgroup\$ – hardwork Aug 19 '16 at 7:28
  • \$\begingroup\$ Not sure why trying to rotate CharacterController component. You rotate the parent transform usually. There is movement control for character controller. \$\endgroup\$ – Sourav Paul Aug 19 '16 at 7:41
1
\$\begingroup\$

Change your sliding animation with translated down position and use root motion of this animation in Unity.

Or use a parent child setup for controlling a character or figure.

In parent keep the Scripts, CharacterController component.

In child keep the character body with animator component.

In the script use GetComponentInChildren<Animator>() instead of GetComponent<Animator>().

When sliding, translate down the child as you need towards ground. Go back to normal position when not sliding. You can resize height of the CharacterController if you need.

You can do it in same object but above way keeps them separate and interfering with each other with better control.

\$\endgroup\$
  • \$\begingroup\$ I tried your script but it cant rotate my collider for every time, It just Rotate it only first time. This is my code if (Input.GetKey (KeyCode.S) && controller.isGrounded) { anim.SetBool ("RunToSlip", true); controller.transform.Rotate (-40, 0, 0); Invoke ("StopSlidding", 0.2f); } and this ` void StopSlidding(){ anim.SetBool ("RunToSlip", false); controller.transform.Rotate (40,0,0); } ` \$\endgroup\$ – hardwork Aug 19 '16 at 7:08
  • \$\begingroup\$ I can't change character controller height because I must have to keep collider for full body mesh. \$\endgroup\$ – hardwork Aug 19 '16 at 7:12
  • \$\begingroup\$ Add you code at question details. \$\endgroup\$ – Sourav Paul Aug 19 '16 at 7:15
  • \$\begingroup\$ I add my code see it. \$\endgroup\$ – hardwork Aug 19 '16 at 7:20
  • \$\begingroup\$ I think controller.transform.Rotate() work before invoke() method start. that's why my player character collider not rotate as I want. And Also Controller rotation not stay with invoke() method to start. controller rotate to zero position before invoke() method start. \$\endgroup\$ – hardwork Aug 19 '16 at 7:34
-1
\$\begingroup\$

@hardwork, I think, and if I read your question right, you could change the location of the animating part, not the controller, whiile it's sliding to have not so mid air. Then, change it back to it's normal location later on. In javaScript, you'd use "transform.position", but I'm not sure if that is it in C#. You can type in that under the Js search, then swap it over to C#.

\$\endgroup\$
  • \$\begingroup\$ I say above it's problem with collider not with animation parts or character position. just try to look other related question on this topic. And transform.position is not any kind of solution for collider. \$\endgroup\$ – hardwork Aug 19 '16 at 13:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.