Advertisement
athos_k

Untitled

Nov 30th, 2016
145
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.82 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3.  
  4. public class CharMove : MonoBehaviour {
  5.  
  6. float moveSpeedMultiplier = 1;
  7.  
  8. float stationaryTurnSpeed = 180; //if the character is not moving, how fast he will turn
  9. float movingTurnSpeed = 360; //same as the above but for when the character is moving
  10.  
  11.  
  12. public bool onGround; //if true the character is on the ground
  13.  
  14. Animator animator;
  15.  
  16. Vector3 moveInput; //The move vector
  17. float turnAmount; //the calculated turn amount to pass to mecanim
  18. float forwardAmount; //the calculated forward amount to pass to mecanim
  19. Vector3 velocity; //the 3d velocity of the character
  20.  
  21. float jumpPower = 10;
  22.  
  23. IComparer rayHitComparer;
  24.  
  25.  
  26. public float autoTurnThreshold = 10;
  27. public float autoTurnSpeed = 20;
  28. bool aim;
  29. Vector3 currentLookPos;
  30.  
  31. public Transform LeftHand;
  32.  
  33. float lastAirTime;
  34. Collider collider;
  35. Rigidbody rigidBody;
  36. public PhysicMaterial highFriction;
  37. public PhysicMaterial lowFriction;
  38. Vector3 GroundNormal;
  39.  
  40. bool inCover;
  41.  
  42. // Use this for initialization
  43. void Start () {
  44. animator = GetComponentInChildren<Animator> ();
  45.  
  46. SetUpAnimator();
  47.  
  48. rigidBody = GetComponent<Rigidbody> ();
  49. collider = GetComponent<Collider> ();
  50. }
  51.  
  52. void SetUpAnimator()
  53. {
  54. // this is a ref to the animator component on the root.
  55. animator = GetComponent<Animator>();
  56.  
  57. // we use avatar from a child animator component if present
  58. // (this is to enable easy swapping of the character model as a child node)
  59. foreach (var childAnimator in GetComponentsInChildren<Animator>()) {
  60. if (childAnimator != animator) {
  61. animator.avatar = childAnimator.avatar;
  62. Destroy (childAnimator);
  63. break; //if you find the first animator, stop searching
  64. }
  65. }
  66.  
  67. LeftHand = animator.GetBoneTransform (HumanBodyBones.LeftHand);
  68. }
  69.  
  70. //Updates the movement of the character based on its current speed and the moveSpeedMultiplier
  71. public void OnAnimatorMove()
  72. {
  73. if(onGround && Time.deltaTime > 0) //If the character is on the ground and is not the first frame of play
  74. {
  75. Vector3 v = (animator.deltaPosition * moveSpeedMultiplier)/ Time.deltaTime; //calculate the speed that the character should have
  76. //Delta position (position difference) - The difference in the position between the current frame and the previous one
  77. //Speed = the position difference of the animator * speed multiplier / time
  78.  
  79. v.y = rigidBody.velocity.y; //store the characters vertical velocity (in order to not to affect jump speed)
  80.  
  81. if(!inCover)
  82. rigidBody.velocity = v; //update the character's speed
  83. else
  84. rigidBody.interpolation = RigidbodyInterpolation.None;
  85. }
  86. }
  87.  
  88.  
  89. public void Move(Vector3 move, bool aim, Vector3 lookPos, bool inCover)
  90. {
  91. //Vector3 move is the input in word space
  92.  
  93. if (move.magnitude > 1) //Make sure that the movement is normalized
  94. move.Normalize ();
  95.  
  96. this.moveInput = move; //store the move
  97. this.aim = aim;
  98. this.inCover = inCover;
  99.  
  100. velocity = GetComponent<Rigidbody>().velocity; //store the current velocity
  101.  
  102. ConvertMoveInput ();
  103.  
  104. //New
  105. this.currentLookPos = lookPos;
  106.  
  107. if(!aim)
  108. {
  109. TurnTowardsCameraForward ();
  110. ApplyExtraTurnRotation ();
  111. }
  112.  
  113. //GroundCheck ();
  114. onGround = true;
  115. //part 4
  116. SetFriction ();
  117.  
  118. // control and velocity handling is different when grounded and airborne:
  119. if (onGround) {
  120. HandleGroundedVelocities();
  121. } else {
  122. HandleAirborneVelocities();
  123. }
  124.  
  125. UpdateAnimator ();
  126.  
  127. }
  128.  
  129. void ConvertMoveInput ()
  130. {
  131. // convert the world relative moveInput vector into a local-relative
  132. // turn amount and forward amount required to head in the desired
  133. // direction.
  134. //convert the move input (e.g. left -> (-1, 0, 0) from the world space to the characters local space
  135. Vector3 localMove = transform.InverseTransformDirection (moveInput);
  136.  
  137. //calculate the turn amount trigonometrically
  138. turnAmount = Mathf.Atan2 (localMove.x, localMove.z);
  139.  
  140. forwardAmount = localMove.z;
  141. }
  142.  
  143. void ApplyExtraTurnRotation ()
  144. {
  145. // help the character turn faster (this is in addition to root rotation in the animation)
  146. //based on movingTurnSpeed and stationaryTurnSpeed and the forward amount of the character
  147.  
  148.  
  149. float turnSpeed = Mathf.Lerp (stationaryTurnSpeed, movingTurnSpeed, forwardAmount);
  150. transform.Rotate (0, turnAmount * turnSpeed * Time.deltaTime, 0);
  151.  
  152. }
  153.  
  154. void UpdateAnimator ()
  155. {
  156. //part 4
  157. if (!inCover)
  158. animator.applyRootMotion = onGround;
  159. else
  160. animator.applyRootMotion = false;
  161.  
  162.  
  163. if(!aim && !inCover)
  164. {
  165. animator.SetFloat ("Forward", forwardAmount, 0.1f, Time.deltaTime);
  166. animator.SetFloat ("Turn", turnAmount, 0.1f, Time.deltaTime);
  167. }
  168.  
  169. animator.SetBool ("Aim", aim);
  170.  
  171. //part 4
  172. animator.SetBool ("OnGround", onGround);
  173.  
  174. }
  175. public float ra2y;
  176. //Checks if the character is on the ground or airborne
  177. void GroundCheck ()
  178. {
  179.  
  180. Ray ray = new Ray (transform.position + Vector3.up * .5f, -Vector3.up);
  181.  
  182. RaycastHit[] hits = Physics.RaycastAll (ray, .5f); //perform a raycast using that ray for a distance of 0.5
  183. rayHitComparer = new RayHitComparer();
  184. System.Array.Sort (hits, rayHitComparer); //sort the hits using our comparer (based on distance)
  185.  
  186. if (velocity.y < jumpPower * .5f)
  187. { //if the character is not airborne due to a jump
  188. //we will talk about jumping in the next tutorials
  189.  
  190. //assume that the character is on the air and falling
  191. // onGround = false;
  192. rigidBody.useGravity = true;
  193.  
  194. foreach (var hit in hits) { //for each of the hits
  195. // check whether we hit a non-trigger collider (and not the character itself)
  196. if (!hit.collider.isTrigger) {
  197. // this counts as being on ground.
  198.  
  199. // stick to surface - helps character stick to ground - specially when running down slopes
  200. //if the character is falling and is close to the ground, we assume that he goes down a slope
  201. if (velocity.y <= 0) {
  202. rigidBody.position = Vector3.MoveTowards (GetComponent<Rigidbody>().position, hit.point, Time.deltaTime * 5);
  203. //change the rigid body potition to the hit point
  204. }
  205.  
  206. onGround = true; //set the on ground variable since we found our collider
  207. rigidBody.useGravity = false; //disable gravity since we use the above to stick the character to the ground
  208.  
  209. break; //ignore the rest of the hits
  210. }
  211. }
  212. }
  213. //part 4
  214. // remember when we were last in air, for jump delay
  215. if (!onGround)
  216. {
  217. lastAirTime = Time.time;
  218. }
  219. }
  220.  
  221.  
  222. //part 4
  223. void SetFriction()
  224. {
  225. //if we are on the ground
  226. if (onGround) {
  227.  
  228. // and we have movement
  229. if (moveInput.magnitude == 0) {
  230. // swap the material to a high friction one
  231. collider.material = highFriction;
  232. } else {
  233. // but when moving, we want no friction:
  234. collider.material = lowFriction;
  235. }
  236. } else {
  237. // while in air, we want no friction against surfaces (walls, ceilings, etc)
  238. collider.material = lowFriction;
  239. }
  240. }
  241.  
  242.  
  243. void HandleGroundedVelocities()
  244. {
  245. //if we are on the ground then we don't want any velocity on the Y
  246. velocity.y = 0;
  247.  
  248. //and if we are not moving, manipulate all the velocities so that we don't slide on slopes
  249. if (moveInput.magnitude == 0) {
  250. velocity.x = 0;
  251. velocity.z = 0;
  252. }
  253. }
  254.  
  255. void HandleAirborneVelocities ()
  256. {
  257. // we allow some movement in air but we only make it to have a small change in the trajectory
  258. Vector3 airMove = new Vector3 (moveInput.x * 6, velocity.y, moveInput.z * 6);
  259. velocity = Vector3.Lerp (velocity, airMove, Time.deltaTime * 2);
  260.  
  261. //we want gravity
  262. rigidBody.useGravity = true;
  263.  
  264. // apply extra gravity from multiplier:
  265. //we want more gravity, so we multiply it by 2 and
  266. Vector3 extraGravityForce = (Physics.gravity * 2);
  267.  
  268. rigidBody.AddForce(extraGravityForce);
  269. }
  270.  
  271.  
  272.  
  273. void TurnTowardsCameraForward ()
  274. {
  275. // automatically turn to face camera direction,
  276. // when not moving, and beyond the specified angle threshold
  277. if (Mathf.Abs (forwardAmount) < .01f) {
  278. //our look direction is the transformed direction from wolrd space to local space
  279. Vector3 lookDelta = transform.InverseTransformDirection (currentLookPos - transform.position);
  280. //Returns the angle in radians Radians-to-degrees conversion
  281. float lookAngle = Mathf.Atan2 (lookDelta.x, lookDelta.z) * Mathf.Rad2Deg;
  282.  
  283. // are we beyond the threshold of where need to turn to face the camera?
  284. if (Mathf.Abs (lookAngle) > autoTurnThreshold) {
  285. turnAmount += lookAngle * autoTurnSpeed * .001f;
  286. }
  287. }
  288. }
  289.  
  290.  
  291.  
  292. //Compares two raycasts based on their distance
  293. class RayHitComparer: IComparer
  294. {
  295. public int Compare(object x, object y)
  296. {
  297. return ((RaycastHit)x).distance.CompareTo(((RaycastHit)y).distance);
  298. //this returns < 0 if x < y
  299. // > 0 if x > y
  300. // 0 if x = y
  301. }
  302. }
  303.  
  304. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement