- Home /
MatchTarget Help
Hello everyone, this is my first post so please be gentle lol. I'm not going to ask any one to write code for me, all I need is some feed back on my current Movement/Climbing system, and I will try to be as descriptive as possible. The way I have approached this is to set up a state machine to handle all of the movement and acrobatics that the player character is capable of. Firstly, I have mad my test scene with an elevated surface on which I want to be able to use target matching to climb onto. The way I have implemented the state change is through box collider triggers.
I created an array of empty game objects with box colliders that are the width of the player character on the x axis, the height of the platform on the y axis, and the distance in which I want to initialize the target match if I press the "Jump" button on the z axis. These "WidthChecker" objects have a child object that is positioned where I want the player character to land on the platform.
[HERES HOW IT LOOKS]
I have a script attached to these game objects that set the target object to the child of the width checker in the OnTriggerEnter call, and set it back to null in the OnTriggerExit call.
This part works fine, however the target match causes an intermittent error that rotates the CharacterController 180 degrees on the x axis so that the player character is lying on his side. Also when the state returns to normal movement, after a few seconds of running away from the platform I am translated back to the x, and z position of the target match destination object.
The other issue is that the character controller's gravity(Even when I set it to 0 in the wall climbing state) affects the Character Controller and makes him fall back to the ground beside the platform. Also I cannot get the Avatar bone targets to match the position of the target match destination object to look natural.
The documentation on this function isn't as robust as it should be and there are a few things that I cannot grasp about it's peramiters.
The first thing is the match rotation. (The second peramiter of the function) Logically I assume that if I set it to be the rotation of the target match destination object it should work out, but it instantly turns the Character controller on it's side. Setting it to be Quaternion.identity seems to somewhat resolve the issue but it's still not the desired affect.
The second thing is the MatchTargetWeightMask. (The fourth peramiter of the function) I've tried to set positionXYZ weight to be the position of the target match destination object in both world and local space but it translates me litteraly all over the place during the target match, and Vector3.one is the only thing that works. I would like to understand this peramiter better.
Also the normalized start and end time seam to be a bit quirky. (The last two peramiters of the function) To the best of my knowledge, these are supposed to be the desired start and end points of the animation clip that you wish to call the target match. I have exposed these variables to play around with them but they do not seem to work appropriately all of the time, I'm still a bit foggy on the details about this.
If there is any one who would be willing to analyze my logic and give me some insight on the direction I need to be going to solve these issues, and just to clear up the inner workings of the MatchTarget function it would be much appreciated.
If any one can help me get this working properly I will make a video tutorial on it and post it on YouTube to hopefully help any one else with the same issues that I am having.
[HERES MY ANIMATION CONTROLLER]
[HERES MY SCRIPT]
Thanks in advance....`
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(CharacterController))]
public class PlayerMovement : MonoBehaviour
{
#region Public Enumerations
//This is the enumeration that stores the state info for the speed at which the character moves.
public enum MoveSpeedState
{
Idle,
Walk,
Run,
Sprint
}
//This is the enumeration that stores the movement states that the character can be in.(IE Accrobatics).
public enum State
{
NormalMovement,
WallClimb
}
#endregion
#region Private Variables
#region Exposed Variables
//These variables are exposed so that they can be tweaked for testing the match target system.
/******************************************************************************************************/
[SerializeField]
private float _normalizedStartTime;
[SerializeField]
private float _normaizedEndTime;
[SerializeField]
private Transform _targetMatchObject;
/******************************************************************************************************/
//These variables are exposed for testing the proper speed of the character controller
/******************************************************************************************************/
[SerializeField]
private float _moveSpeed;
[SerializeField]
private float _walkSpeed = 2;
[SerializeField]
private float _runSpeed = 6;
[SerializeField]
private float _sprintSpeed = 9;
[SerializeField]
private float _rotationSpeed = 100;
[SerializeField]
private float _gravity = 20;
[SerializeField]
private float _jumpHeight = 8;
/******************************************************************************************************/
#endregion
//This variable will be used to set up a while loop when the script is switched to an FSM.
private bool _alive = true;
//Used for returning information about ray's cast from the player.
private RaycastHit _racastHit;
//This is a reference to the Animator compenent of the player character.
private Animator _animator;
//This is the variable that calculates the vector math for the player character.
private Vector3 _moveDirection = Vector3.zero;
//This is a cached version of the Transform componenet of the player character root object.
private Transform _myTransform;
//This is a reference to the CharacterController component of the the player character root object.
private CharacterController _characterController;
//This is used to return the current state of the Animator Controller asset used by the player character.
private AnimatorStateInfo _animatorStateInfo;
//These are private references to the state references defined in the public enumerations at the top of this script.
private State _state;
private MoveSpeedState _moveSpeedState;
#endregion
#region Getters & Setters
//This is used to access the target that the match target function accesses publicly from outside of this script.
public Transform TargetMatchObject
{
get{return _targetMatchObject;}
set{_targetMatchObject = value;}
}
#endregion
#region System Methods
private void Awake()
{
//Here we initialize the movement speed to be equale to the run speed variable.
_moveSpeed = _runSpeed;
//Assign the animator component reference.
_animator = GetComponent<Animator>();
//Assign the CharacterController component reference.
_characterController = GetComponent<CharacterController>();
//Assign the Transform component reference.
_myTransform = this.transform;
//Assign the enumeration references.
_state = State.NormalMovement;
_moveSpeedState = MoveSpeedState.Run;
}
private void Start()
{
//Assign the State info reference for the Animator Controller.
_animatorStateInfo = _animator.GetCurrentAnimatorStateInfo(0);
}
private void Update()
{
//These will be calculated every frame.
/*********************/
CalculateMoveSpeed();
/*********************/
//State machine that governs all of the movement capabilities that the player can be in.
switch(_state)
{
case State.NormalMovement:
//Allows for rotation of the CharacterController on the x axis with damping applied.
_myTransform.Rotate(0, Input.GetAxis("Rotate") * _rotationSpeed * Time.deltaTime, 0);
//Only execute the folling code if the CharacterController is touching the ground.
if(_characterController.isGrounded == true)
{
//Temporary floats that store the values of the Input Axis
/******************************************************************************************************/
float Rotate = Input.GetAxis("Rotate");
float Movement = Input.GetAxis("Movement");
/******************************************************************************************************/
//Set the Animator Controller float peramitors to equal the value of the Input Axis.
/******************************************************************************************************/
_animator.SetFloat("Speed", Movement);
_animator.SetFloat("Direction", Rotate);
/******************************************************************************************************/
//Make the vector calculations to move the character controller.
/******************************************************************************************************/
_moveDirection = new Vector3(0, 0, Input.GetAxisRaw("Movement"));
_moveDirection = _myTransform.TransformDirection(_moveDirection);
_moveDirection *= _moveSpeed;
/******************************************************************************************************/
//Setup the Jump button conditions if the Character controller is grounded.
if(Input.GetButtonDown("Jump"))
{
//Switch the state if the _targetMatchObject exists.
if(_targetMatchObject != null)
{
_state = State.WallClimb;
}
//If the _targetMatchObject does not exist, calculate the normal jump behaviour.
else if(_targetMatchObject == null)
{
_moveDirection.y = _jumpHeight;
}
}
}
//If the state is currently in Normal movement, make the global behaviour calculations here.
/******************************************************************************************************/
_moveDirection.y -= _gravity * Time.deltaTime;
_characterController.Move(_moveDirection * Time.deltaTime);
/******************************************************************************************************/
break;
case State.WallClimb:
//Initialize the calculation to enter into the target match for wall climbing, then reset the state to normal movement at the appropriate time.
// TODO: Use the AnimatorStateInfo to calculate the position of the target match math instead of a Coroutine.
/******************************************************************************************************/
//Initializ the playback of the Climb Up animation.
_animator.SetBool("ClimbUp", true);
//Start the calculation to time the point at which the state returns to normal movement.
StartCoroutine("CalculateEndOfTargetMatch");
//Initialize the target match function.
_animator.MatchTarget(_targetMatchObject.transform.position, Quaternion.identity, AvatarTarget.LeftFoot, new MatchTargetWeightMask(Vector3.one, _targetMatchObject.transform.rotation.y), _normalizedStartTime, _normaizedEndTime);
/******************************************************************************************************/
break;
}
}
#endregion
#region Calculation Methods
private void CalculateMoveSpeed()
{
//State machine that governs the move speed.
// TODO: set up the Animator Controller states for normal movement in here.
switch(_moveSpeedState)
{
case MoveSpeedState.Idle:
_moveSpeed = 0.0f;
break;
case MoveSpeedState.Walk:
_moveSpeed = _walkSpeed;
break;
case MoveSpeedState.Run:
_moveSpeed = _runSpeed;
break;
case MoveSpeedState.Sprint:
_moveSpeed = _sprintSpeed;
break;
}
}
//This is the coroutine used to calculate the timing of the state change from "WallClimb" to "NormalMovement".
private IEnumerator CalculateEndOfTargetMatch()
{
//Set the time to wait until the Movement State Changes.
yield return new WaitForSeconds(_normaizedEndTime);
//Break the playback of the Animator Controller's call to the "ClimbUp" animation state.
_animator.SetBool("ClimbUp", false);
//Change the state back to "NormalMovement".
_state = State.NormalMovement;
}
#endregion
}
I$$anonymous$$HO, seems that at line 197 when you create new $$anonymous$$atchTargetWeight$$anonymous$$ask at second parametr must be number 0 to 1 as it is weight mask.
Your answer
Follow this Question
Related Questions
How to make climbable zone more than one? 0 Answers
Issues with Apply Root Motion for Climbing up 0 Answers
climbing in oculus touch 0 Answers
Character that Climbs Everything Including On Ceiling 1 Answer
2d-platformer climb 2 Answers