1 using System;
2 using
UnityEngine;
3 using
UnityStandardAssets.CrossPlatformInput;
4 using
UnityStandardAssets.Utility;
5 using
Random = UnityEngine.Random;
6
7 namespace
UnityStandardAssets.Characters.FirstPerson
8 {
9     
[RequireComponent(typeof (CharacterController))]
10     
[RequireComponent(typeof (AudioSource))]
11     
public class FirstPersonController : MonoBehaviour
12     {
13         [SerializeField]
private bool m_IsWalking;
14         [SerializeField]
private float m_WalkSpeed;
15         [SerializeField]
private float m_RunSpeed;
16         [SerializeField] [Range(
0f, 1f)] private float m_RunstepLenghten;
17         [SerializeField]
private float m_JumpSpeed;
18         [SerializeField]
private float m_StickToGroundForce;
19         [SerializeField]
private float m_GravityMultiplier;
20         [SerializeField]
private MouseLook m_MouseLook;
21         [SerializeField]
private bool m_UseFovKick;
22         [SerializeField]
private FOVKick m_FovKick = new FOVKick();
23         [SerializeField]
private bool m_UseHeadBob;
24         [SerializeField]
private CurveControlledBob m_HeadBob = new CurveControlledBob();
25         [SerializeField]
private LerpControlledBob m_JumpBob = new LerpControlledBob();
26         [SerializeField]
private float m_StepInterval;
27         [SerializeField]
private AudioClip[] m_FootstepSounds; // an array of footstep sounds that will be randomly selected from.
28         [SerializeField]
private AudioClip m_JumpSound; // the sound played when character leaves the ground.
29         [SerializeField]
private AudioClip m_LandSound; // the sound played when character touches back on ground.
30
31         
private Camera m_Camera;
32         
private bool m_Jump;
33         
private float m_YRotation;
34         
private Vector2 m_Input;
35         
private Vector3 m_MoveDir = Vector3.zero;
36         
private CharacterController m_CharacterController;
37         
private CollisionFlags m_CollisionFlags;
38         
private bool m_PreviouslyGrounded;
39         
private Vector3 m_OriginalCameraPosition;
40         
private float m_StepCycle;
41         
private float m_NextStep;
42         
private bool m_Jumping;
43         
private AudioSource m_AudioSource;
44
45         
// Use this for initialization
46         
private void Start()
47         {
48             m_CharacterController = GetComponent<CharacterController>();
49             m_Camera = Camera.main;
50             m_OriginalCameraPosition = m_Camera.transform.localPosition;
51             m_FovKick.Setup(m_Camera);
52             m_HeadBob.Setup(m_Camera, m_StepInterval);
53             m_StepCycle =
0f;
54             m_NextStep = m_StepCycle/
2f;
55             m_Jumping =
false;
56             m_AudioSource = GetComponent<AudioSource>();
57             m_MouseLook.Init(transform , m_Camera.transform);
58         }
59
60
61         
// Update is called once per frame
62         
private void Update()
63         {
64             RotateView();
65             
// the jump state needs to read here to make sure it is not missed
66             
if (!m_Jump)
67             {
68                 m_Jump = CrossPlatformInputManager.GetButtonDown(
"Jump");
69             }
70
71             
if (!m_PreviouslyGrounded && m_CharacterController.isGrounded)
72             {
73                 StartCoroutine(m_JumpBob.DoBobCycle());
74                 PlayLandingSound();
75                 m_MoveDir.y =
0f;
76                 m_Jumping =
false;
77             }
78             
if (!m_CharacterController.isGrounded && !m_Jumping && m_PreviouslyGrounded)
79             {
80                 m_MoveDir.y =
0f;
81             }
82
83             m_PreviouslyGrounded = m_CharacterController.isGrounded;
84         }
85
86
87         
private void PlayLandingSound()
88         {
89             m_AudioSource.clip = m_LandSound;
90             m_AudioSource.Play();
91             m_NextStep = m_StepCycle + .
5f;
92         }
93
94
95         
private void FixedUpdate()
96         {
97             
float speed;
98             GetInput(
out speed);
99             
// always move along the camera forward as it is the direction that it being aimed at
100             Vector3 desiredMove = transform.forward*m_Input.y + transform.right*m_Input.x;
101
102             
// get a normal for the surface that is being touched to move along it
103             RaycastHit hitInfo;
104             Physics.SphereCast(transform.position, m_CharacterController.radius, Vector3.down,
out hitInfo,
105                                m_CharacterController.height/
2f, ~0, QueryTriggerInteraction.Ignore);
106             desiredMove = Vector3.ProjectOnPlane(desiredMove, hitInfo.normal).normalized;
107
108             m_MoveDir.x = desiredMove.x*speed;
109             m_MoveDir.z = desiredMove.z*speed;
110
111
112             
if (m_CharacterController.isGrounded)
113             {
114                 m_MoveDir.y = -m_StickToGroundForce;
115
116                 
if (m_Jump)
117                 {
118                     m_MoveDir.y = m_JumpSpeed;
119                     PlayJumpSound();
120                     m_Jump =
false;
121                     m_Jumping =
true;
122                 }
123             }
124             
else
125             {
126                 m_MoveDir += Physics.gravity*m_GravityMultiplier*Time.fixedDeltaTime;
127             }
128             m_CollisionFlags = m_CharacterController.Move(m_MoveDir*Time.fixedDeltaTime);
129
130             ProgressStepCycle(speed);
131             UpdateCameraPosition(speed);
132
133             m_MouseLook.UpdateCursorLock();
134         }
135
136
137         
private void PlayJumpSound()
138         {
139             m_AudioSource.clip = m_JumpSound;
140             m_AudioSource.Play();
141         }
142
143
144         
private void ProgressStepCycle(float speed)
145         {
146             
if (m_CharacterController.velocity.sqrMagnitude > 0 && (m_Input.x != 0 || m_Input.y != 0))
147             {
148                 m_StepCycle += (m_CharacterController.velocity.magnitude + (speed*(m_IsWalking ?
1f : m_RunstepLenghten)))*
149                              Time.fixedDeltaTime;
150             }
151
152             
if (!(m_StepCycle > m_NextStep))
153             {
154                 
return;
155             }
156
157             m_NextStep = m_StepCycle + m_StepInterval;
158
159             PlayFootStepAudio();
160         }
161
162
163         
private void PlayFootStepAudio()
164         {
165             
if (!m_CharacterController.isGrounded)
166             {
167                 
return;
168             }
169             
// pick & play a random footstep sound from the array,
170             
// excluding sound at index 0
171             
int n = Random.Range(1, m_FootstepSounds.Length);
172             m_AudioSource.clip = m_FootstepSounds[n];
173             m_AudioSource.PlayOneShot(m_AudioSource.clip);
174             
// move picked sound to index 0 so it's not picked next time
175             m_FootstepSounds[n] = m_FootstepSounds[
0];
176             m_FootstepSounds[
0] = m_AudioSource.clip;
177         }
178
179
180         
private void UpdateCameraPosition(float speed)
181         {
182             Vector3 newCameraPosition;
183             
if (!m_UseHeadBob)
184             {
185                 
return;
186             }
187             
if (m_CharacterController.velocity.magnitude > 0 && m_CharacterController.isGrounded)
188             {
189                 m_Camera.transform.localPosition =
190                     m_HeadBob.DoHeadBob(m_CharacterController.velocity.magnitude +
191                                       (speed*(m_IsWalking ?
1f : m_RunstepLenghten)));
192                 newCameraPosition = m_Camera.transform.localPosition;
193                 newCameraPosition.y = m_Camera.transform.localPosition.y - m_JumpBob.Offset();
194             }
195             
else
196             {
197                 newCameraPosition = m_Camera.transform.localPosition;
198                 newCameraPosition.y = m_OriginalCameraPosition.y - m_JumpBob.Offset();
199             }
200             m_Camera.transform.localPosition = newCameraPosition;
201         }
202
203
204         
private void GetInput(out float speed)
205         {
206             
// Read input
207             
float horizontal = CrossPlatformInputManager.GetAxis("Horizontal");
208             
float vertical = CrossPlatformInputManager.GetAxis("Vertical");
209
210             
bool waswalking = m_IsWalking;
211
212 #
if !MOBILE_INPUT
213             
// On standalone builds, walk/run speed is modified by a key press.
214             
// keep track of whether or not the character is walking or running
215             m_IsWalking = !Input.GetKey(KeyCode.LeftShift);
216 #endif
217             
// set the desired speed to be walking or running
218             speed = m_IsWalking ? m_WalkSpeed : m_RunSpeed;
219             m_Input =
new Vector2(horizontal, vertical);
220
221             
// normalize input if it exceeds 1 in combined length:
222             
if (m_Input.sqrMagnitude > 1)
223             {
224                 m_Input.Normalize();
225             }
226
227             
// handle speed change to give an fov kick
228             
// only if the player is going to a run, is running and the fovkick is to be used
229             
if (m_IsWalking != waswalking && m_UseFovKick && m_CharacterController.velocity.sqrMagnitude > 0)
230             {
231                 StopAllCoroutines();
232                 StartCoroutine(!m_IsWalking ? m_FovKick.FOVKickUp() : m_FovKick.FOVKickDown());
233             }
234         }
235
236
237         
private void RotateView()
238         {
239             m_MouseLook.LookRotation (transform, m_Camera.transform);
240         }
241
242
243         
private void OnControllerColliderHit(ControllerColliderHit hit)
244         {
245             Rigidbody body = hit.collider.attachedRigidbody;
246             
//dont move the rigidbody if the character is on top of it
247             
if (m_CollisionFlags == CollisionFlags.Below)
248             {
249                 
return;
250             }
251
252             
if (body == null || body.isKinematic)
253             {
254                 
return;
255             }
256             body.AddForceAtPosition(m_CharacterController.velocity*
0.1f, hit.point, ForceMode.Impulse);
257         }
258     }
259 }


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