1 using System;
2 using
UnityEngine;
3 using
UnityStandardAssets.CrossPlatformInput;
4
5 namespace
UnityStandardAssets.Characters.FirstPerson
6 {
7     
[RequireComponent(typeof (Rigidbody))]
8     
[RequireComponent(typeof (CapsuleCollider))]
9     
public class RigidbodyFirstPersonController : MonoBehaviour
10     {
11         
[Serializable]
12         
public class MovementSettings
13         {
14             
public float ForwardSpeed = 8.0f; // Speed when walking forward
15             
public float BackwardSpeed = 4.0f; // Speed when walking backwards
16             
public float StrafeSpeed = 4.0f; // Speed when walking sideways
17             
public float RunMultiplier = 2.0f; // Speed when sprinting
18             
public KeyCode RunKey = KeyCode.LeftShift;
19             
public float JumpForce = 30f;
20             
public AnimationCurve SlopeCurveModifier = new AnimationCurve(new Keyframe(-90.0f, 1.0f), new Keyframe(0.0f, 1.0f), new Keyframe(90.0f, 0.0f));
21             [HideInInspector]
public float CurrentTargetSpeed = 8f;
22
23 #
if !MOBILE_INPUT
24             
private bool m_Running;
25 #endif
26
27             
public void UpdateDesiredTargetSpeed(Vector2 input)
28             {
29                 
if (input == Vector2.zero) return;
30                 
if (input.x > 0 || input.x < 0)
31                 {
32                     
//strafe
33                     CurrentTargetSpeed = StrafeSpeed;
34                 }
35                 
if (input.y < 0)
36                 {
37                     
//backwards
38                     CurrentTargetSpeed = BackwardSpeed;
39                 }
40                 
if (input.y > 0)
41                 {
42                     
//forwards
43                     
//handled last as if strafing and moving forward at the same time forwards speed should take precedence
44                     CurrentTargetSpeed = ForwardSpeed;
45                 }
46 #
if !MOBILE_INPUT
47                 
if (Input.GetKey(RunKey))
48                 {
49                     CurrentTargetSpeed *= RunMultiplier;
50                     m_Running =
true;
51                 }
52                 
else
53                 {
54                     m_Running =
false;
55                 }
56 #endif
57             }
58
59 #
if !MOBILE_INPUT
60             
public bool Running
61             {
62                 
get { return m_Running; }
63             }
64 #endif
65         }
66
67
68         
[Serializable]
69         
public class AdvancedSettings
70         {
71             
public float groundCheckDistance = 0.01f; // distance for checking if the controller is grounded ( 0.01f seems to work best for this )
72             
public float stickToGroundHelperDistance = 0.5f; // stops the character
73             
public float slowDownRate = 20f; // rate at which the controller comes to a stop when there is no input
74             
public bool airControl; // can the user control the direction that is being moved in the air
75             
[Tooltip("set it to 0.1 or more if you get stuck in wall")]
76             
public float shellOffset; //reduce the radius by that ratio to avoid getting stuck in wall (a value of 0.1f is nice)
77         }
78
79
80         
public Camera cam;
81         
public MovementSettings movementSettings = new MovementSettings();
82         
public MouseLook mouseLook = new MouseLook();
83         
public AdvancedSettings advancedSettings = new AdvancedSettings();
84
85
86         
private Rigidbody m_RigidBody;
87         
private CapsuleCollider m_Capsule;
88         
private float m_YRotation;
89         
private Vector3 m_GroundContactNormal;
90         
private bool m_Jump, m_PreviouslyGrounded, m_Jumping, m_IsGrounded;
91
92
93         
public Vector3 Velocity
94         {
95             
get { return m_RigidBody.velocity; }
96         }
97
98         
public bool Grounded
99         {
100             
get { return m_IsGrounded; }
101         }
102
103         
public bool Jumping
104         {
105             
get { return m_Jumping; }
106         }
107
108         
public bool Running
109         {
110             
get
111             {
112  #
if !MOBILE_INPUT
113                 
return movementSettings.Running;
114 #
else
115                 
return false;
116 #endif
117             }
118         }
119
120
121         
private void Start()
122         {
123             m_RigidBody = GetComponent<Rigidbody>();
124             m_Capsule = GetComponent<CapsuleCollider>();
125             mouseLook.Init (transform, cam.transform);
126         }
127
128
129         
private void Update()
130         {
131             RotateView();
132
133             
if (CrossPlatformInputManager.GetButtonDown("Jump") && !m_Jump)
134             {
135                 m_Jump =
true;
136             }
137         }
138
139
140         
private void FixedUpdate()
141         {
142             GroundCheck();
143             Vector2 input = GetInput();
144
145             
if ((Mathf.Abs(input.x) > float.Epsilon || Mathf.Abs(input.y) > float.Epsilon) && (advancedSettings.airControl || m_IsGrounded))
146             {
147                 
// always move along the camera forward as it is the direction that it being aimed at
148                 Vector3 desiredMove = cam.transform.forward*input.y + cam.transform.right*input.x;
149                 desiredMove = Vector3.ProjectOnPlane(desiredMove, m_GroundContactNormal).normalized;
150
151                 desiredMove.x = desiredMove.x*movementSettings.CurrentTargetSpeed;
152                 desiredMove.z = desiredMove.z*movementSettings.CurrentTargetSpeed;
153                 desiredMove.y = desiredMove.y*movementSettings.CurrentTargetSpeed;
154                 
if (m_RigidBody.velocity.sqrMagnitude <
155                     (movementSettings.CurrentTargetSpeed*movementSettings.CurrentTargetSpeed))
156                 {
157                     m_RigidBody.AddForce(desiredMove*SlopeMultiplier(), ForceMode.Impulse);
158                 }
159             }
160
161             
if (m_IsGrounded)
162             {
163                 m_RigidBody.drag =
5f;
164
165                 
if (m_Jump)
166                 {
167                     m_RigidBody.drag =
0f;
168                     m_RigidBody.velocity =
new Vector3(m_RigidBody.velocity.x, 0f, m_RigidBody.velocity.z);
169                     m_RigidBody.AddForce(
new Vector3(0f, movementSettings.JumpForce, 0f), ForceMode.Impulse);
170                     m_Jumping =
true;
171                 }
172
173                 
if (!m_Jumping && Mathf.Abs(input.x) < float.Epsilon && Mathf.Abs(input.y) < float.Epsilon && m_RigidBody.velocity.magnitude < 1f)
174                 {
175                     m_RigidBody.Sleep();
176                 }
177             }
178             
else
179             {
180                 m_RigidBody.drag =
0f;
181                 
if (m_PreviouslyGrounded && !m_Jumping)
182                 {
183                     StickToGroundHelper();
184                 }
185             }
186             m_Jump =
false;
187         }
188
189
190         
private float SlopeMultiplier()
191         {
192             
float angle = Vector3.Angle(m_GroundContactNormal, Vector3.up);
193             
return movementSettings.SlopeCurveModifier.Evaluate(angle);
194         }
195
196
197         
private void StickToGroundHelper()
198         {
199             RaycastHit hitInfo;
200             
if (Physics.SphereCast(transform.position, m_Capsule.radius * (1.0f - advancedSettings.shellOffset), Vector3.down, out hitInfo,
201                                    ((m_Capsule.height/
2f) - m_Capsule.radius) +
202                                    advancedSettings.stickToGroundHelperDistance, ~
0, QueryTriggerInteraction.Ignore))
203             {
204                 
if (Mathf.Abs(Vector3.Angle(hitInfo.normal, Vector3.up)) < 85f)
205                 {
206                     m_RigidBody.velocity = Vector3.ProjectOnPlane(m_RigidBody.velocity, hitInfo.normal);
207                 }
208             }
209         }
210
211
212         
private Vector2 GetInput()
213         {
214             
215             Vector2 input =
new Vector2
216                 {
217                     x = CrossPlatformInputManager.GetAxis(
"Horizontal"),
218                     y = CrossPlatformInputManager.GetAxis(
"Vertical")
219                 };
220             movementSettings.UpdateDesiredTargetSpeed(input);
221             
return input;
222         }
223
224
225         
private void RotateView()
226         {
227             
//avoids the mouse looking if the game is effectively paused
228             
if (Mathf.Abs(Time.timeScale) < float.Epsilon) return;
229
230             
// get the rotation before it's changed
231             
float oldYRotation = transform.eulerAngles.y;
232
233             mouseLook.LookRotation (transform, cam.transform);
234
235             
if (m_IsGrounded || advancedSettings.airControl)
236             {
237                 
// Rotate the rigidbody velocity to match the new direction that the character is looking
238                 Quaternion velRotation = Quaternion.AngleAxis(transform.eulerAngles.y - oldYRotation, Vector3.up);
239                 m_RigidBody.velocity = velRotation*m_RigidBody.velocity;
240             }
241         }

242
243         ///
sphere cast down just beyond the bottom of the capsule to see if the capsule is colliding round the bottom
244         
private void GroundCheck()
245         {
246             m_PreviouslyGrounded = m_IsGrounded;
247             RaycastHit hitInfo;
248             
if (Physics.SphereCast(transform.position, m_Capsule.radius * (1.0f - advancedSettings.shellOffset), Vector3.down, out hitInfo,
249                                    ((m_Capsule.height/
2f) - m_Capsule.radius) + advancedSettings.groundCheckDistance, ~0, QueryTriggerInteraction.Ignore))
250             {
251                 m_IsGrounded =
true;
252                 m_GroundContactNormal = hitInfo.normal;
253             }
254             
else
255             {
256                 m_IsGrounded =
false;
257                 m_GroundContactNormal = Vector3.up;
258             }
259             
if (!m_PreviouslyGrounded && m_IsGrounded && m_Jumping)
260             {
261                 m_Jumping =
false;
262             }
263         }
264     }
265 }


Gõ tìm kiếm nhanh...