Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
using UnityEngine;
using System.Collections;
public class ZeroGravCC : MonoBehaviour {
float moveSpeed = 6; // move speed
float turnSpeed = 90; // turning speed (degrees/second)
float lerpSpeed = 10; // smoothing speed
float gravity = 10; // gravity acceleration
bool isGrounded;
float deltaGround = 0.2f; // character is grounded up to this distance
float jumpSpeed = 10; // vertical jump initial speed
float jumpRange = 10; // range to detect target wall
private Vector3 surfaceNormal; // current surface normal
private Vector3 myNormal; // character normal
private float distGround; // distance from character position to ground
private bool jumping = false; // flag "I'm jumping to wall"
private float vertSpeed = 0; // vertical jump current speed
private Rigidbody rb;
// private ThirdPersonCharacter thirdPersonScript;
void Start(){
myNormal = transform.up; // normal starts as character up direction
rb.freezeRotation = true; // disable physics rotation
// distance from transform.position to ground
distGround = transform.position.y - 0f;
rb = gameObject.GetComponent<Rigidbody>();
// thirdPersonScript = gameObject.GetComponent<ThirdPersonCharacter>();
}
void FixedUpdate(){
// apply constant weight force according to character normal:
rb.AddForce(-gravity*rb.mass*myNormal);
}
void Update(){
// jump code - jump to wall or simple jump
if (jumping) return; // abort Update while jumping to a wall
Ray ray;
RaycastHit hit;
if (Input.GetButtonDown("Jump")){ // jump pressed:
if (Physics.Raycast(transform.position, -myNormal, out hit, jumpRange)){ // wall ahead?
// JumpToWall(hit.point, hit.normal); // yes: jump to the wall
}
else if (isGrounded){ // no: if grounded, jump up
rb.velocity += jumpSpeed * myNormal;
}
}
// movement code - turn left/right with Horizontal axis:
transform.Rotate(0, Input.GetAxis("Horizontal")*turnSpeed*Time.deltaTime, 0);
// update surface normal and isGrounded:
if (Physics.Raycast(transform.position, -myNormal, out hit, Mathf.Infinity)){ // use it to update myNormal and isGrounded
isGrounded = hit.distance <= distGround + deltaGround;
surfaceNormal = hit.normal;
// thirdPersonScript.newNormal = surfaceNormal;
}
else {
isGrounded = false;
// assume usual ground normal to avoid "falling forever"
surfaceNormal = Vector3.up;
}
myNormal = Vector3.Lerp(myNormal, surfaceNormal, lerpSpeed*Time.deltaTime);
// find forward direction with new myNormal:
var myForward = Vector3.Cross(transform.right, myNormal);
// align character to the new myNormal while keeping the forward direction:
var targetRot = Quaternion.LookRotation(myForward, myNormal);
transform.rotation = Quaternion.Lerp(transform.rotation, targetRot, lerpSpeed*Time.deltaTime);
// move the character forth/back with Vertical axis:
transform.Translate(0, 0, Input.GetAxis("Vertical")*moveSpeed*Time.deltaTime);
}
// public void JumpToWall(Vector3 point, Vector3 normal){
// // jump to wall
// jumping = true; // signal it's jumping to wall
// rb.isKinematic = true; // disable physics while jumping
// var orgPos = transform.position;
// var orgRot = transform.rotation;
// var dstPos = point + normal * (distGround + 0.5); // will jump to 0.5 above wall
// var myForward = Vector3.Cross(transform.right, normal);
// var dstRot = Quaternion.LookRotation(myForward, normal);
// for (float t = 0.0; t < 1.0; ){
// t += Time.deltaTime;
// transform.position = Vector3.Lerp(orgPos, dstPos, t);
// transform.rotation = Quaternion.Slerp(orgRot, dstRot, t);
// yield; // return here next frame
// }
// myNormal = normal; // update myNormal
// rigidbody.isKinematic = false; // enable physics
// jumping = false; // jumping to wall finished
// }
}