首页 > 技术文章 > 角色控制器以及玩家水平垂直视角转动

yuanxiaoyu 2021-11-05 18:26 原文

角色控制器以及玩家水平垂直视角转动

角色控制器 (Character Controller) 主要用于第三人称玩家控制或者是不使用__刚体__物理组件的第一人称玩家控制
 

控制器本身不会对力作出反应,也不会自动推开刚体。

Move 为 GameObject 的移动提供附加的 CharacterController 组件。
 

 

如果要通过角色控制器来推动刚体或对象,可以编写脚本通过 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}

 

 
 
 
 
 
 
 
 
 
 
 
 
 
 

 

推荐阅读