当前位置:   article > 正文

unity实现第一人称的打靶(射箭)游戏_unity怎么做射击

unity怎么做射击

目录

游戏要求

项目地址与视频展示

玩家动作表(游戏规则表)

图形设计

弩弓与弩箭设计

靶子设计

天空盒设计

地形设计

动画控制器设计

原理及代码设计

弩弓与弩箭的实现Bow

玩家移动控制器PlayerMove

设计区域控制ShootingArea

靶子各个区域不同得分的控制Target

控制靶子的移动TargetMove

提示和积分管理Tips

天空盒切换SkyboxSwitcher

主相机(主视觉)移动控制器CameraMove


游戏要求

本项目游戏是3D游戏设计的一个期中大作业,其中具体的实验要求如下所示:

  •  地形:使用地形组件,上面有草、树;
  •  天空盒:使用天空盒,天空可随玩家位置 或 时间变化 或 按特定按键切换天空盒;
  •  固定靶:有一个以上固定的靶标;
  •  运动靶:有一个以上运动靶标,运动轨迹,速度使用动画控制;
  •  射击位:地图上应标记若干射击位,仅在射击位附近可以拉弓射击,每个位置有 n 次机会;
  •  驽弓动画:支持蓄力半拉弓,然后 hold,择机 shoot;
  •  游走:玩家的驽弓可在地图上游走,不能碰上树和靶标等障碍;
  •  碰撞与计分:在射击位,射中靶标的相应分数,规则自定;

项目地址与视频展示

本游戏项目的代码仓库地址为:github的仓库地址

本游戏项目的演示视频地址为:本打靶(射箭)游戏演示视频

玩家动作表(游戏规则表)

动作条件结果
WASD

玩家(弩弓)在设计好的地形上

玩家(弩弓)前后左右移动
按下鼠标右键天空盒发生变化

玩家(弩弓)

移动

玩家(弩弓)与树木、靶子发生碰撞玩家(弩弓)停止移动
按下鼠标左键玩家(弩弓)在射击位置上弩弓开始蓄力
长按鼠标左键弩弓的拉力不断增加直至所设定的上限
松开鼠标左键弩弓根据长按的时间所计算的拉力来发射弩箭
鼠标移动玩家(第一人称)的视觉范围发生变化
弩箭射中靶子弩箭的碰撞检测体与靶子的碰撞检测体发生碰撞总得分根据我们为每一个靶子所设定的分数进行增加

图形设计

弩弓与弩箭设计

在本游戏项目中,我们采用的弩弓与弩箭预制体为导入的资源包里面的预制体和model,采用的是资源商店里面下载的Classical Crossbow。如图所示:

靶子设计

通过不同大小、不同形状的基础物体来构成。最外面的绿色区域为Cube,白色区域为Cylinder,而最里面的靶心(红色)区域也是为Cylinder,通过修改其半径来显示不同的Cylinder,同时还需要为靶子不同的部分构建不同的碰撞检测体。最后将这一个构成的集合物体建成预制体,以供生成后面的靶子。

天空盒设计

在本次游戏项目中,我们还需要实现天空盒的切换,而我在这里采用的方法就是通过按动鼠标右键来切换天空盒。我们首先需要构建天空盒,我们可以直接从资源商店中导入相应的资源,我们导入的是资源是8K Skybox Pack Free,在这一个资源中,我们可以看到有很多个天空盒供我们自己选择,我们随便选择两种来实现天空盒的切换即可。我们采用的是天空盒3和天空盒10。

地形设计

我们首先通过鼠标左键添加3D对象中的Terrain,然后根据Inspector界面中的不同选择来对地形进行修改和描绘,可以增高或降低地形,可以为地形增加不同的纹理。我们还可以为地形种树,我们选择不同的树木,然后点击Terrain即可实现种树的功能。一样的,我们还可以选择种草,我们选择不一样的小草,然后点击Terrain即可实现种草的功能。我们可以通过不同的选项来实现对地形进行不同的修改功能。

动画控制器设计

在本游戏项目中,主要的动画控制为弩箭的蓄力、发射等,我们导入的资源中,它已经自带了一些动作包以及一个动画控制器,我们可以直接采用才动画控制器,然后在这个的基础上进行修改即可。

原理及代码设计

弩弓与弩箭的实现Bow

1. Start(): 游戏开始时的初始化操作。设置时间缩放为正常速度,获取弓的动画控制器,锁定鼠标光标。

2. Update(): 每帧执行的更新操作:

       检测是否按下了 Escape 键来切换光标锁定状态。
       检测是否按下了鼠标左键来切换光标锁定状态。 
       检查射击区域是否存在,如果不存在则隐藏箭的数量文本并返回。
       如果射击区域存在,显示箭的数量文本,并更新箭的数量显示。
       检查是否可以射击箭,并且当前还有剩余的箭。
       如果按下鼠标左键,重置拉动开始时间,触发弓的拉动动画,并调用 FindBullet() 函数清除场         景中的箭。
       如果按住鼠标左键,增加拉动箭头的时间,并将该时间值设置为弓的拉动动画的参数。
       如果松开鼠标左键,将拉动距离设为拉动开始时间,重置拉动开始时间,触发弓的射击动               画,并调用 ShootArrow() 函数发射箭,并在1.5秒后调用 FindShootingArea() 函数查找射击           区域。
3. ShootArrow(): 发射箭的函数。实例化箭游戏对象,获取箭的刚体组件,根据拉动距离设置箭的速度,减少射击区域的箭数量,并更新箭的数量显示。

4. FindBullet(): 清除场景中的箭的函数。通过标签找到所有的箭游戏对象,然后销毁它们。

5. FindShootingArea(): 查找射击区域的函数。通过标签找到所有的射击区域游戏对象,检查它们是否还有剩余的箭。如果没有任何射击区域剩余箭了,解锁光标,显示游戏结束的 UI,并将时间缩放设为0,即暂停游戏。

6. LockCursor(bool a): 锁定/解锁光标的函数。根据传入的布尔值来切换光标的锁定状态和可见性。如果传入 true,则锁定光标并隐藏;如果传入 false,则解锁光标并显示。

  1. using UnityEngine;
  2. using UnityEngine.UI;
  3. public class Bow : MonoBehaviour
  4. {
  5. //导入箭的预制体
  6. public GameObject arrowPrefab;
  7. //箭的Transform组件
  8. public Transform arrowSpawnPoint;
  9. //弓的最大拉动距离
  10. public float maxPullDistance = 3f;
  11. //弓的最大拉动力度
  12. public float maxPullForce = 100f;
  13. //弓的最小拉动时间
  14. public float minPullTime = 1f;
  15. //弓的最大拉动时间
  16. public float maxPullTime = 5f;
  17. //箭的飞行速度
  18. public float arrowFlightSpeed = 10f;
  19. //开始的拉动时间
  20. private float pullStartTime;
  21. //拉动的距离
  22. private float pullDistance;
  23. //弓的动画控制器
  24. private Animator anim;
  25. //射击区域
  26. public ShootingArea shootingArea;
  27. //箭的数量text
  28. public Text arrowCountTxt;
  29. //箭的数量UI
  30. public GameObject arrowCount;
  31. //游戏介绍的UI
  32. public GameObject over;
  33. void Start()
  34. {
  35. Time.timeScale = 1;
  36. anim = GetComponent<Animator>();
  37. LockCursor(true);
  38. }
  39. private void Update()
  40. {
  41. if (Input.GetKeyDown(KeyCode.Escape) && Cursor.visible) { LockCursor(false); }
  42. if (Input.GetMouseButtonDown(0) && Cursor.visible == false) { LockCursor(true); }
  43. if (shootingArea == null)
  44. {
  45. arrowCount.SetActive(false);
  46. return;
  47. }
  48. else
  49. {
  50. arrowCount.SetActive(true);
  51. arrowCountTxt.text = "箭数:" + shootingArea.arrowCount;
  52. }
  53. if (shootingArea.isArrow && shootingArea.arrowCount > 0)
  54. {
  55. if (Input.GetMouseButtonDown(0))
  56. {
  57. pullStartTime = 0;
  58. anim.SetTrigger("hold");
  59. //调用该函数清除场景中的箭
  60. FindBullet();
  61. }
  62. else if (Input.GetMouseButton(0))
  63. {
  64. //增加拉动箭头的时间
  65. pullStartTime += Time.deltaTime;
  66. //将拉动箭头的时间设置为前面计算得到的时间
  67. anim.SetFloat("holdTime", pullStartTime);
  68. }//玩家松开鼠标左键释放箭
  69. else if (Input.GetMouseButtonUp(0))
  70. {
  71. pullDistance = pullStartTime;
  72. pullStartTime = 0;
  73. anim.SetTrigger("shoot");
  74. ShootArrow();
  75. Invoke("FindShootingArea", 1.5f);
  76. }
  77. }
  78. }
  79. private void ShootArrow()
  80. {
  81. // 实例化箭
  82. GameObject arrow = Instantiate(arrowPrefab, arrowSpawnPoint.position, arrowSpawnPoint.rotation);
  83. Rigidbody arrowRigidbody = arrow.GetComponent<Rigidbody>();
  84. //根据拉动距离给箭设定速度
  85. arrowRigidbody.velocity = transform.forward * pullDistance * 30f;
  86. shootingArea.arrowCount -= 1;
  87. arrowCountTxt.text = "箭数:" + shootingArea.arrowCount;
  88. }
  89. public void FindBullet()
  90. {
  91. var bullets = GameObject.FindGameObjectsWithTag("Bullet");
  92. for (int i = 0; i < bullets.Length; i++)
  93. {
  94. Destroy(bullets[i]);
  95. }
  96. }
  97. public void FindShootingArea()
  98. {
  99. var ShootingAreas = GameObject.FindGameObjectsWithTag("ShootingArea");
  100. var temp = 0;
  101. for (int i = 0; i < ShootingAreas.Length; i++)
  102. {
  103. if (ShootingAreas[i].transform.GetComponent<ShootingArea>().arrowCount > 0)
  104. {
  105. temp++;
  106. }
  107. }
  108. if (temp <= 0)
  109. {
  110. LockCursor(false);
  111. over.SetActive(true);
  112. Time.timeScale = 0;
  113. }
  114. }
  115. public void LockCursor(bool a)
  116. {
  117. if (a)
  118. {
  119. Cursor.lockState = CursorLockMode.Locked;
  120. Cursor.visible = false;
  121. }
  122. else
  123. {
  124. Cursor.lockState = CursorLockMode.None;
  125. Cursor.visible = true;
  126. }
  127. }
  128. }

玩家移动控制器PlayerMove

1. Start(): 游戏开始时的初始化操作。获取角色的 CharacterController 组件。

2. Update(): 每帧执行的更新操作。调用 Move() 函数来处理角色的移动逻辑。

3. Move(): 处理角色移动的函数:

        通过输入获取水平方向(X轴)和垂直方向(Z轴)的按键输入值。
        根据输入值计算出移动方向,并将其乘以移动速度和时间增量,得到最终的移动向量。
        使用 CharacterController 的 Move() 方法来移动角色,传入计算得到的移动向量。
        根据重力值和时间增量,更新垂直方向上的速度(velocity.y)。
        再次使用 CharacterController 的 Move() 方法来应用垂直方向上的速度变化,使角色受到重            力影响下落或上升。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class PlayerMove : MonoBehaviour
  5. {
  6. //人物控制器
  7. private CharacterController controller;
  8. //人物移动速度
  9. public float speed = 2f;
  10. public float gravity = -15f;
  11. Vector3 velocity;
  12. private void Start()
  13. {
  14. controller = GetComponent<CharacterController>();
  15. }
  16. // Update is called once per frame
  17. void Update()
  18. {
  19. Move();
  20. }
  21. public void Move()
  22. {
  23. //键盘输入
  24. float x = Input.GetAxis("Horizontal");
  25. float z = Input.GetAxis("Vertical");
  26. Vector3 move = transform.right * x + transform.forward * z;
  27. controller.Move(move * speed * Time.deltaTime);
  28. velocity.y += gravity * Time.deltaTime;
  29. controller.Move(velocity * Time.deltaTime);
  30. }
  31. }

射击区域控制ShootingArea

1. arrowCount: 用于记录射击区域内剩余的箭的数量,初始值为10。

2. isArrow: 用于表示射击区域内是否有可用的箭。

3. isPlayer: 用于记录玩家是否在射击区域内。

4. OnTriggerStay(Collider other): 当有物体停留在射击区域内时触发的函数:

       检查如果玩家已经在射击区域内,直接返回,不执行后续操作。
       检查与射击区域碰撞的物体是否具有 "Player" 标签。
       如果是玩家物体发生碰撞:
       更新相关的变量,将 isPlayer 和 isArrow 设置为 true。
       获取玩家物体上的 Bow 脚本,并将射击区域设置为当前的脚本。

5. OnTriggerExit(Collider other): 当有物体离开射击区域时触发的函数:

       检查离开触发器的物体是否具有 "Player" 标签。
       如果是玩家物体离开:
       更新相关变量,将 isPlayer 设置为 false。
       检查玩家物体上的 Bow 脚本的 shootingArea 是否为 null。
       如果不为 null,将射击区域内的箭矢数量赋值给玩家物体上的 Bow 脚本的射击区域的箭矢数           量。
       将 isArrow 设置为 false。
       将玩家物体上的 Bow 脚本的射击区域设置为 null。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class ShootingArea : MonoBehaviour
  5. {
  6. //将该区域的可用箭数初始化为10
  7. public int arrowCount = 10;
  8. //设置一个变量记录该区域是否有箭
  9. public bool isArrow;
  10. //记录玩家是否在区域内
  11. private bool isPlayer;
  12. private void OnTriggerStay(Collider other)
  13. {
  14. //如果玩家已经在区域内
  15. if (isPlayer) return;
  16. //如果该区域的触发器与标签为player的玩家发生碰撞
  17. if (other.gameObject.tag == "Player")
  18. {
  19. //更新相关的变量
  20. isPlayer = true;
  21. isArrow = true;
  22. //获取玩家物体上的脚本,并且将射击区域设置为当前的脚本
  23. other.gameObject.transform.GetComponent<Bow>().shootingArea = this;
  24. }
  25. }
  26. private void OnTriggerExit(Collider other)
  27. {
  28. //如果触发器与标签为player的玩家离开碰撞
  29. if (other.gameObject.tag == "Player")
  30. {
  31. //更新相关变量
  32. isPlayer = false;
  33. if (other.gameObject.transform.GetComponent<Bow>().shootingArea != null)
  34. {
  35. //将射击区域内的箭矢数量赋值给玩家物体上的Bow脚本的射击区域的箭矢数量
  36. arrowCount = other.gameObject.transform.GetComponent<Bow>().shootingArea.arrowCount;
  37. }
  38. isArrow = false;
  39. //将玩家物体上的Bow脚本的射击区域设置为null
  40. other.gameObject.transform.GetComponent<Bow>().shootingArea = null;
  41. }
  42. }
  43. }

靶子各个区域不同得分的控制Target

1. score: 靶子的得分,初始值为1。

2. isSportsTarget: 表示靶子是否为运动靶子。

3. point: 靶子的位置点的Transform组件。

4. indexTarget: 靶子的索引。

5. Start(): 在脚本启动时进行初始化操作。获取靶子的父对象作为位置点。

6. OnCollisionEnter(Collision collision): 当靶子弩箭弹发生碰撞时触发的函数:

       检查碰撞的物体是否具有 "Bullet" 标签。
           如果是弩箭发生碰撞:
               调用 CalculateScore() 函数计算得分。
               将碰撞的弩箭的刚体设为运动学(isKinematic),停止其物理模拟。
               将碰撞点的位置稍微偏移并将弩箭放置在靶子的位置点下。
                将弩箭的父对象设置为位置点。
7. CalculateScore(): 计算得分的函数:

       检查靶子的标签。
           如果靶子的标签为 "Bullseye",表示击中了靶心:
               检查靶子是否为运动靶子。
                   如果是运动靶子,将得分加10,并显示相应的提示信息。
                   如果不是运动靶子,将得分加8,并显示相应的提示信息。
           如果靶子的标签为 "Circle",表示击中了白色区域:
                检查靶子是否为运动靶子。
                    如果是运动靶子,将得分加5,并显示相应的提示信息。
                    如果不是运动靶子,将得分加3,并显示相应的提示信息。

  1. using UnityEngine;
  2. public class Target : MonoBehaviour
  3. {
  4. //得分
  5. public int score = 1;
  6. //是否为运动靶子
  7. public bool isSportsTarget;
  8. //靶子的位置点
  9. private Transform point;
  10. //靶子的索引
  11. public int indexTarget;
  12. private void Start()
  13. {
  14. //获取靶子的父对象作为位置点
  15. point = transform.parent;
  16. }
  17. private void OnCollisionEnter(Collision collision)
  18. {
  19. if (collision.gameObject.CompareTag("Bullet"))
  20. {
  21. // 调用函数计算得分
  22. CalculateScore();
  23. collision.transform.GetComponent<Rigidbody>().isKinematic = true;
  24. collision.transform.position = new Vector3(collision.contacts[0].point.x, collision.contacts[0].point.y, collision.contacts[0].point.z - Random.Range(-0.3f, -0.5f));
  25. collision.gameObject.transform.parent = point;
  26. }
  27. }
  28. private void CalculateScore()
  29. {
  30. //如果靶子的标签为Bullseye,即为靶心
  31. if (gameObject.tag == "Bullseye")
  32. {
  33. // 如果为运动靶子
  34. if (isSportsTarget)
  35. {
  36. // 将得分加3
  37. Tips.Instance.SetScore(10);
  38. Tips.Instance.SetText("在" + indexTarget + "号射击位上射中" + indexTarget + "号靶子,加10分");
  39. }
  40. else
  41. {
  42. //如果不是运动靶子,将得分加2
  43. Tips.Instance.SetScore(8);
  44. Tips.Instance.SetText("在" + indexTarget + "号射击位上射中" + indexTarget + "号靶子,加3分");
  45. }
  46. }
  47. // 如果靶子的标签为Circle,即为白色区域
  48. else if (gameObject.tag == "Circle")
  49. {
  50. //如果为运动靶子
  51. if (isSportsTarget)
  52. {
  53. // 将得分加2
  54. Tips.Instance.SetScore(5);
  55. Tips.Instance.SetText("在" + indexTarget + "号射击位上射中" + indexTarget + "号靶子,加5分");
  56. }
  57. else
  58. {
  59. // 如果不是运动靶子,就将得分加1
  60. Tips.Instance.SetScore(3);
  61. Tips.Instance.SetText("在" + indexTarget + "号射击位上射中" + indexTarget + "号靶子,加3分");
  62. }
  63. }
  64. }
  65. }

控制靶子的移动TargetMove

1. speed: 靶子的移动速度。

2. distance: 靶子的移动距离。

3. startPosition: 靶子的起始位置。

4. direction: 靶子的移动方向,初始值为1。

5. Start(): 在脚本启动时进行初始化操作。记录靶子的起始位置。

6. Update(): 在每一帧更新时执行的函数:

       计算下一帧的位置,根据当前位置、移动速度、移动方向和时间间隔来计算。
       判断下一帧的位置与起始位置之间的距离是否超过设定的移动距离。
           如果超过移动距离,改变移动方向(乘以-1),以实现来回移动。
       更新靶子的位置为计算得到的下一帧位置。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class TargetMove : MonoBehaviour
  5. {
  6. //靶子的移动速度
  7. public float speed = 5f;
  8. //靶子的移动距离
  9. public float distance = 10f;
  10. //靶子的起始位置
  11. private Vector3 startPosition;
  12. //靶子的移动方向
  13. private float direction = 1f;
  14. void Start()
  15. {
  16. //记录起始位置
  17. startPosition = transform.position;
  18. }
  19. void Update()
  20. {
  21. //计算下一帧的位置
  22. Vector3 nextPosition = transform.position + new Vector3(speed * direction * Time.deltaTime, 0f, 0f);
  23. // 判断是否超出移动范围,超出则改变移动方向
  24. if (Vector3.Distance(startPosition, nextPosition) > distance)
  25. {
  26. direction *= -1f;
  27. }
  28. // 更新位置
  29. transform.position = nextPosition;
  30. }
  31. }

提示和得分管理Tips

1. Instance: Tips类的静态实例,用于在其他脚本中访问Tips类的实例。

2. tips: 提示框的游戏对象。

3. tipsText: 提示文本的Text组件。

4. score: 当前的得分。

5. scoreText: 显示得分的Text组件。

6. Awake(): 在脚本被加载时执行的函数。将Tips类的实例设置为当前实例。

7. SetText(string str): 设置提示文本的函数:

       接收一个字符串参数,用于设置提示文本的内容。
       将提示文本设置为接收的字符串。
       激活提示框的游戏对象,使其可见。
8. SetScore(int score): 设置得分的函数:

       接收一个整数参数,表示要增加的得分。
       将接收的得分加到当前的得分上。
       将得分显示在得分文本中,格式为 "分数: 得分值"。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. public class Tips : MonoBehaviour
  6. {
  7. public static Tips Instance;
  8. public GameObject tips;
  9. public Text tipsText;
  10. private int score;
  11. public Text scoreText;
  12. private void Awake()
  13. {
  14. Instance = this;
  15. }
  16. public void SetText(string str)
  17. {
  18. tipsText.text = str;
  19. tips.SetActive(true);
  20. }
  21. public void SetScore(int score)
  22. {
  23. this.score += score;
  24. scoreText.text = "分数:" + this.score;
  25. }
  26. }

天空盒切换SkyboxSwitcher

1. skybox1: 第一个天空盒的材质。

2. skybox2: 第二个天空盒的材质。

3. isSkybox1Active: 当前激活的天空盒是否为天空盒1的标志,初始值为true。

4. Update(): 在每一帧更新时执行的函数:

       检测是否按下鼠标右键(按钮编号为1)。
       如果按下右键,调用SwitchSkybox()函数切换天空盒。
5. SwitchSkybox(): 切换天空盒的函数:

       切换天空盒的状态,将isSkybox1Active的值取反。
       如果isSkybox1Active为true,将渲染设置中的天空盒材质设置为第一个天空盒材质。
       如果isSkybox1Active为false,将渲染设置中的天空盒材质设置为第二个天空盒材质。

  1. using UnityEngine;
  2. public class SkyboxSwitcher : MonoBehaviour
  3. {
  4. //第一个天空盒
  5. public Material skybox1;
  6. //第二个天空盒
  7. public Material skybox2;
  8. //当前激活的天空盒是否为天空盒1
  9. private bool isSkybox1Active = true;
  10. private void Update()
  11. {
  12. //如果按下C键,切换天空盒
  13. if (Input.GetMouseButtonDown(1))
  14. {
  15. SwitchSkybox();
  16. }
  17. }
  18. private void SwitchSkybox()
  19. {
  20. //切换天空盒的状态
  21. isSkybox1Active = !isSkybox1Active;
  22. if (isSkybox1Active)
  23. {
  24. //设置渲染设置中的天空盒材质为第一个天空盒材质
  25. RenderSettings.skybox = skybox1;
  26. }
  27. else
  28. {
  29. //设置渲染设置中的天空盒材质为第二个天空盒材质
  30. RenderSettings.skybox = skybox2;
  31. }
  32. }
  33. }

主相机(主视觉)移动控制器CameraMove

1. mouseXSensitivity: 鼠标在X轴上的灵敏度,用于控制视角旋转的速度。

2. player: 用于存储玩家对象的Transform组件。

3. xRotation: 控制视角绕X轴旋转的角度。

4. Start(): 在脚本启动时执行的函数:

       获取父级对象的Transform组件并赋值给player变量。
5. Update(): 在每一帧更新时执行的函数:

       获取鼠标在X轴和Y轴上的移动距离(输入值)并乘以鼠标灵敏度和时间间隔。
       将Y轴移动距离(mouseY)累加到xRotation上,用于控制视角绕X轴旋转。
       限制xRotation的值在-45到10之间,以限制视角的上下旋转幅度。
       将当前的xRotation应用于摄像机的本地旋转,实现视角的上下旋转。
       将X轴移动距离(mouseX)乘以玩家对象的向上方向(Vector3.up)应用于玩家对象的旋               转,实现视角的左右旋转。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. //鼠标控制视角
  5. public class CameraMove : MonoBehaviour
  6. {
  7. //鼠标x轴灵敏度
  8. public float mouseXSensitivity = 25f;
  9. //人物
  10. private Transform player;
  11. //旋转角度
  12. float xRotation = 0f;
  13. private void Start()
  14. {
  15. player = transform.parent.transform;
  16. }
  17. // Update is called once per frame
  18. void Update()
  19. {
  20. float mouseX = Input.GetAxis("Mouse X") * mouseXSensitivity * Time.deltaTime;
  21. float mouseY = Input.GetAxis("Mouse Y") * mouseXSensitivity * Time.deltaTime;
  22. xRotation -= mouseY;
  23. //y轴最大旋转角度为正负90;
  24. xRotation = Mathf.Clamp(xRotation, -45f, 10f);
  25. transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
  26. player.Rotate(Vector3.up * mouseX);
  27. }
  28. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/104201
推荐阅读
相关标签
  

闽ICP备14008679号