• 【Unity3D】摇杆


    1 需求实现

            1)需求实现

    • 鼠标拖拽摇杆球控制坦克移动;
    • 上下左右按键也可以控制坦克移动,并且摇杆球也同步移动;
    • 鼠标右键滑动,控制坦克转向;
    • 相机在玩家后上方的位置,始终跟随玩家,朝玩家正前方看;
    • 单击鼠标左键或按空格键控制坦克发射炮弹。

            2)涉及技术栈

    2 游戏对象

            1)游戏界面

            2)游戏对象层级结构

            3)Transform组件参数

            1. 玩家 Transform 组件参数

    NameTypePositionRotationScaleColor/Texture
    PlayerEmpty(0, 0.25, -5)(0, 0, 0)(1, 1, 1)#228439FF
    BottonCube(0, 0, 0)(0, 0, 0)(2, 0.5, 2)#228439FF
    TopCube(0, 0.5, 0)(0, 0, 0)(1, 0.5, 1)#228439FF
    GunCylinder(0, 0, 1.5)(90, 0, 0)(0.2, 1, 0.4)#228439FF
    FirePointEmpty(0, 1.15, 0)(0, 0, 0)(1, 1, 1)——

            补充:Player 游戏对象添加了刚体组件。 

            2. 地面和炮弹 Transform 组件参数

    NameTypePositionRotationScaleColor/Texture
    PlanePlane(0, 0, 0)(0, 0, 0)(10, 10, 10)GrassRockyAlbedo
    BulletSphere(0, 0.5, -5)(0, 0, 0)(0.3, 0.3, 0.3)#228439FF

            补充:炮弹作为预设体拖拽到 Assets/Resources/Prefabs 目录下,并且添加了刚体组件。

            3. 摇杆 RectTransform 组件参数

    NameTypeWidth/HeightPosAnchors
    StickCanvas——————
    BackgroundImage(100, 100)(75, 75, 0)(0, 0), (0, 0)
    BallImage(40, 40)(75, 75, 0)(0, 0), (0, 0)

    3 脚本组件

            1)CameraController

            CameraController.cs

    1. using UnityEngine;
    2. public class CameraController : MonoBehaviour {
    3. private Transform player; // 玩家
    4. private Vector3 relaPlayerPos; // 相机在玩家坐标系中的位置
    5. private float targetDistance = 15f; // 相机看向玩家前方的位置
    6. private void Start() {
    7. relaPlayerPos = new Vector3(0, 4, -8);
    8. player = GameObject.Find("Player/Top").transform;
    9. }
    10. private void LateUpdate() {
    11. CompCameraPos();
    12. }
    13. private void CompCameraPos() { // 计算相机坐标
    14. Vector3 target = player.position + player.forward * targetDistance;
    15. transform.position = transformVecter(relaPlayerPos, player.position, player.right, player.up, player.forward);
    16. transform.rotation = Quaternion.LookRotation(target - transform.position);
    17. }
    18. // 求以origin为原点, locX, locY, locZ 为坐标轴的本地坐标系中的向量 vec 在世界坐标系中对应的向量
    19. private Vector3 transformVecter(Vector3 vec, Vector3 origin, Vector3 locX, Vector3 locY, Vector3 locZ) {
    20. return vec.x * locX + vec.y * locY + vec.z * locZ + origin;
    21. }
    22. }

            说明: CameraController 脚本组件挂在 MainCamera 游戏对象上。

            2)PlayerController

            PlayerController.cs

    1. using System;
    2. using UnityEngine;
    3. public class PlayerController : MonoBehaviour {
    4. private Transform firePoint; // 开火点
    5. private GameObject bulletPrefab; // 炮弹预设体
    6. private StickController stick; // 摇杆控制器
    7. private float tankMoveSpeed = 4f; // 坦克移动速度
    8. private float tankRotateSpeed = 2f; // 坦克转向速度
    9. private Vector3 predownMousePoint; // 鼠标按下时的位置
    10. private Vector3 currMousePoint; // 当前鼠标位置
    11. private float fireWaitTime = float.MaxValue; // 距离上次开火已等待的时间
    12. private float bulletCoolTime = 0.15f; // 炮弹冷却时间
    13. private void Start() {
    14. firePoint = transform.Find("Top/Gun/FirePoint");
    15. bulletPrefab = (GameObject) Resources.Load("Prefabs/Bullet");
    16. stick = GameObject.Find("Stick/Ball").GetComponent();
    17. }
    18. private void Update() {
    19. Move();
    20. Rotate();
    21. Fire();
    22. }
    23. private void Move() { // 坦克移动
    24. float hor = Input.GetAxis("Horizontal");
    25. float ver = Input.GetAxis("Vertical");
    26. Move(hor, ver);
    27. }
    28. public void Move(float hor, float ver) { // 坦克移动
    29. if (Mathf.Abs(hor) > float.Epsilon || Mathf.Abs(ver) > float.Epsilon) {
    30. Vector3 vec = transform.forward * ver + transform.right * hor;
    31. GetComponent().velocity = vec * tankMoveSpeed;
    32. // stick.UpdateStick(new Vector3(hor, 0, ver));
    33. Vector3 dire = new Vector3(hor, ver, 0);
    34. dire = dire.normalized * Mathf.Min(dire.magnitude, 1);
    35. stick.UpdateStick(dire);
    36. }
    37. }
    38. private void Rotate() { // 坦克旋转
    39. if (Input.GetMouseButtonDown(1)) {
    40. predownMousePoint = Input.mousePosition;
    41. } else if (Input.GetMouseButton(1)) {
    42. currMousePoint = Input.mousePosition;
    43. Vector3 vec = currMousePoint - predownMousePoint;
    44. GetComponent().angularVelocity = Vector3.up * tankRotateSpeed * vec.x;
    45. predownMousePoint = currMousePoint;
    46. }
    47. }
    48. private void Fire() { // 坦克开炮
    49. fireWaitTime += Time.deltaTime;
    50. if (Input.GetMouseButtonDown(0) && !IsMouseInUIArea() || Input.GetKeyDown(KeyCode.Space)) {
    51. if (fireWaitTime > bulletCoolTime) {
    52. BulletInfo bulletInfo = new BulletInfo("PlayerBullet", Color.red, transform.forward, 10f, 15f);
    53. GameObject bullet = Instantiate(bulletPrefab, firePoint.position, Quaternion.identity);
    54. bullet.AddComponent().SetBulletInfo(bulletInfo);
    55. fireWaitTime = 0f;
    56. }
    57. }
    58. }
    59. private bool IsMouseInUIArea() { // 鼠标在UI控件区域
    60. Vector3 pos = Input.mousePosition;
    61. return pos.x < 150 && pos.y < 150;
    62. }
    63. }

            说明: PlayerController 脚本组件挂在 Player 游戏对象上。 

            3)StickController

            StickController.cs

    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using UnityEngine.EventSystems;
    4. public class StickController : MonoBehaviour, IDragHandler, IEndDragHandler {
    5. private Vector3 originPos; // 鼠标开始拖拽时位置
    6. private Vector3 currPos; // 鼠标当前位置
    7. private float radius; // 遥杆半径
    8. private PlayerController player; // 玩家控制器
    9. private Vector3 dire = Vector3.zero; // 摇杆球的方位
    10. private void Start () {
    11. originPos = transform.position;
    12. radius = 50;
    13. player = GameObject.Find("Player").GetComponent();
    14. }
    15. private void Update () {
    16. player.Move(dire.x, dire.y);
    17. }
    18. public void OnDrag(PointerEventData eventData) {
    19. Vector3 vec = Input.mousePosition - originPos;
    20. dire = vec.normalized * Mathf.Min(vec.magnitude / radius, 1);
    21. UpdateStick(dire);
    22. }
    23. public void OnEndDrag(PointerEventData eventData) {
    24. transform.position = originPos;
    25. dire = Vector3.zero;
    26. }
    27. public void UpdateStick(Vector3 dire) { // 更新摇杆位置
    28. transform.position = originPos + dire * radius;
    29. }
    30. }

            说明: StickController 脚本组件挂在 Ball 游戏对象上。  

            4)BulletController

            BulletController.cs

    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. public class BulletController : MonoBehaviour {
    4. private BulletInfo bulletInfo; // 炮弹信息
    5. private void Start () {
    6. gameObject.name = bulletInfo.name;
    7. GetComponent().material.color = bulletInfo.color;
    8. float lifeTime = bulletInfo.fireRange / bulletInfo.speed; // 存活时间
    9. Destroy(gameObject, lifeTime);
    10. }
    11. private void Update () {
    12. transform.GetComponent().velocity = bulletInfo.flyDir * bulletInfo.speed;
    13. }
    14. public void SetBulletInfo(BulletInfo bulletInfo) {
    15. this.bulletInfo = bulletInfo;
    16. }
    17. }

            说明: BulletController 脚本组件挂在 Bullet 游戏对象上(代码里动态添加)。   

            5)BulletInfo

            BulletInfo.cs

    1. using UnityEngine;
    2. public class BulletInfo {
    3. public string name; // 炮弹名
    4. public Color color; // 炮弹颜色
    5. public Vector3 flyDir; // 炮弹飞出方向
    6. public float speed; // 炮弹飞行速度
    7. public float fireRange; // 炮弹射程
    8. public BulletInfo(string name, Color color, Vector3 flyDir, float speed, float fireRange) {
    9. this.name = name;
    10. this.color = color;
    11. this.flyDir = flyDir;
    12. this.speed = speed;
    13. this.fireRange = fireRange;
    14. }
    15. }

    4 运行效果

  • 相关阅读:
    猿创征文|盘点刚使用ubuntu时建议下载的软件
    【springboot单元测试,集成测试】
    Nginx日志功能介绍
    NFNet:NF-ResNet的延伸,不用BN的4096超大batch size训练 | 21年论文
    【学网攻】 第(27)节 -- HSRP(热备份路由器协议)
    认识 mysql 命令
    【PAT甲级 - C++题解】1103 Integer Factorization
    声学——声源定位阅读笔记
    windows电脑连接Android和iPhone真机调试
    java任务跟踪系统
  • 原文地址:https://blog.csdn.net/m0_37602827/article/details/125986322