角色控制器以及玩家水平垂直视角转动
角色控制器以及玩家水平垂直视角转动
角色控制器 (Character Controller) 主要用于第三人称玩家控制或者是不使用__刚体__物理组件的第一人称玩家控制
控制器本身不会对力作出反应,也不会自动推开刚体。
|
如果要通过角色控制器来推动刚体或对象,可以编写脚本通过 OnControllerColliderHit() 函数对与控制器碰撞的任何对象施力。
OnControllerColliderHit |
当该控制器在执行 Move 时撞到碰撞体时调用 OnControllerColliderHit。
|
OnCollisionEnter | 当该碰撞体/刚体已开始接触另一个刚体/碰撞体时,调用 OnCollisionEnter。 |
OnCollisionExit | 当该碰撞体/刚体已停止接触另一个刚体/碰撞体时,调用 OnCollisionExit。 |
OnCollisionStay | 对应正在接触刚体/碰撞体的每一个碰撞体/刚体,每帧调用一次 OnCollisionStay。 |
OnTriggerEnter | GameObject 与另一个 GameObject 碰撞时,Unity 会调用 OnTriggerEnter。 |
OnTriggerExit | 当 Collider other 已停止接触该触发器时调用 OnTriggerExit。 |
OnTriggerStay | 对于正在接触该触发器的每个其他 Collider,“几乎”所有帧都调用 OnTriggerStay。此函数位于物理计时器上,因此它不必运行每个帧。 |
另一方面,如果希望玩家角色受到物理组件的影响,那么可能更适合使用刚体,而不是角色控制器。(摘自Unity官网API)
具体参数设置如下:
设置玩家的Scale为(2,2,2,)设置中心为Y:0.5,高度为1,半径为0.4,大小位置匹配合适后,新建一个脚本文件,命名为Ryun_PlayerController,编辑脚本:
首先要实现角色的水平垂直视角的转动:
<注>
MonoBehaviour.Update 更新
当MonoBehaviour启用时,其Update在每一帧被调用。
MonoBehaviour.FixedUpdate 固定更新
当MonoBehaviour启用时,其 FixedUpdate在每一帧被调用。
处理Rigidbody时,需要用FixedUpdate代替Update。例如:给刚体加一个作用力时,你必须应用作用力在FixedUpdate里的固定帧,而不是Update中的帧。(两者帧长不同) FixedUpdate是真实时间;Update是在每次渲染新的一帧的时候才会调用
在开始定义:
private float x_Limit = 60;
并在函数体限制X方向的旋转角度的范围:(这是很有必要的,因为欧拉角受到万向锁 (Gimbal Lock) 的影响。当依次施加三个旋转时,第一个或第二个旋转可能导致第三个轴的方向与先前两个轴之一相同。这意味着已失去“自由度”,因为不能围绕唯一轴应用第三个旋转值。)
x_RotateOffset = Mathf.Clamp(x_RotateOffset, -x_Limit, x_Limit);
1 using System.Collections; 2 using System.Collections.Generic; 3 using UnityEngine; 4 5 public class Ryun_PlayerController : MonoBehaviour 6 { 7 public float rotatespeed = 180;//设置鼠标的旋转速度为180 8 [Range(1, 2)]//设置一个Range特性将rotateRatio特性限制在(1,2)之间。 9 public float rotateRatio = 1;//用于设置敏捷度;(当前鼠标增量乘以轴灵敏度) 10 public Transform playerTr; 11 public Transform eye_viewTr; 12 13 private float x_RotateOffset; 14 private float x_Limit = 60; 15 16 public CharacterController PlayCC; 17 public float movespeed = 10; 18 public Transform CheckPoint; 19 public float gravity = 2f; 20 public float vspeed = 0; 21 public bool isground = false; 22 public float radius = 0.8f; 23 public LayerMask ground; 24 public float maxheight = 5; 25 26 public Transform bulletstartpoint; 27 public GameObject bullet; 28 public float bulletstartspeed = 100; 29 public float fireinterval = 0.1f; 30 public bool isFire = false; 31 32 public Ryun_HoveranimationController animatorcontroller; 33 34 // Start is called before the first frame update 35 void Start() 36 { 37 PlayCC = this.GetComponent<CharacterController>(); 38 animatorcontroller = this.GetComponent<Ryun_HoveranimationController> (); 39 } 40 41 // Update is called once per frame 42 void Update() 43 { 44 OpenFire(); 45 } 46 47 private void FixedUpdate() 48 { 49 PlayerRotateControl(); 50 PlayMove(); 51 } 52 53 private void PlayerRotateControl()//自定义一个PlayerRotateControl()函数,并让它在FixedUpdate函数调用 54 { 55 if (playerTr == null || eye_viewTr == null) return; 56 57 58 float offset_x = Input.GetAxis("Mouse X"); 59 float offset_y = Input.GetAxis("Mouse Y");//返回由 axisName 标识的虚拟轴的值。 60 61 playerTr.Rotate(Vector3.up * offset_x * rotatespeed * rotateRatio * Time.fixedDeltaTime); 62 x_RotateOffset += offset_y * rotatespeed * rotateRatio * Time.fixedDeltaTime;//计算出每帧绕X方向的旋转角度的累加值 63 x_RotateOffset = Mathf.Clamp(x_RotateOffset, -x_Limit, x_Limit);//限制X方向的旋转角度的范围 64 65 eye_viewTr.localRotation = Quaternion.Euler(new Vector3(x_RotateOffset, 66 eye_viewTr.localEulerAngles.y, eye_viewTr.localEulerAngles.z)); 67 //返回一个旋转,它围绕 z 轴旋转 z 度、围绕 x 轴旋转 x 度、围绕 y 轴旋转 y 度(按该顺序应用)。代码用于更新每帧旋转后eye_viewTr.localRotation的位置 68 69 } 70 71 private void PlayMove() 72 { 73 if (PlayCC == null) return; 74 Vector3 motionvalue = Vector3.zero; 75 float h = Input.GetAxis("Horizontal"); 76 float v = Input.GetAxis("Vertical"); 77 78 motionvalue -= this.transform.forward * movespeed * v * Time.fixedDeltaTime; 79 motionvalue -= this.transform.right * movespeed * h * Time.fixedDeltaTime; 80 81 vspeed += -gravity * Time.fixedDeltaTime; 82 83 motionvalue += Vector3.up * vspeed * movespeed * Time.fixedDeltaTime; 84 85 if (CheckPoint != null) 86 { 87 if (Physics.CheckSphere(CheckPoint.position, radius, ground) && vspeed < 0) 88 { 89 90 isground = true; 91 vspeed = 0; 92 93 } 94 95 96 } 97 98 if (isground) 99 { 100 if (Input.GetButtonDown("Jump")) 101 { 102 103 vspeed = Mathf.Sqrt(maxheight * 2 / gravity) * gravity; 104 105 } 106 107 108 } 109 110 PlayCC.Move(motionvalue); 111 112 if (animatorcontroller) 113 { 114 animatorcontroller.movespeed = movespeed * v; 115 animatorcontroller.alerted = v == 0 ? false:true; 116 } 117 } 118 119 private void OpenFire() 120 { 121 if (Input.GetMouseButtonDown(0)) 122 { 123 isFire = true; 124 StartCoroutine("Fire"); 125 126 } 127 if (Input.GetMouseButton(0)) 128 { 129 130 131 132 } 133 if (Input.GetMouseButtonUp(0)) 134 { 135 136 isFire = false; 137 StopCoroutine("Fire"); 138 139 } 140 141 142 } 143 IEnumerator Fire() 144 { 145 while (isFire == true) 146 { 147 if (bulletstartpoint != null || bullet != null) 148 { 149 GameObject newbullet = Instantiate(bullet, bulletstartpoint.position, bulletstartpoint.rotation); 150 newbullet.GetComponent<Rigidbody>().velocity = newbullet.transform.forward * -bulletstartspeed; 151 152 Destroy(newbullet, 5); 153 154 } 155 156 yield return new WaitForSeconds(fireinterval);//中断函数 157 158 } 159 } 160}