当前位置:   article > 正文

Unity3D项目:射击打靶_unity 打靶训练

unity 打靶训练

 游戏设计

  • 游戏内容要求
    •  地形:使用地形组件,上面有草、树;
    •   天空盒:使用天空盒,天空可随玩家位置 或 时间变化 或 按特定按键切换天空盒;
    •   固定靶:有一个以上固定的靶标;
    •   运动靶:有一个以上运动靶标,运动轨迹,速度使用动画控制;
    •   射击位:地图上应标记若干射击位,仅在射击位附近可以拉弓射击,每个位置有 n 次机会;
    •  驽弓动画:支持蓄力半拉弓,然后 hold,择机 shoot;
    •  游走:玩家的驽弓可在地图上游走,不能碰上树和靶标等障碍;
    •  碰撞与计分:在射击位,射中靶标的相应分数,规则自定; 
  • 玩家动作表(游戏规则表):
动作条件结果
WASD玩家在地形组件上角色移动
角色移动角色碰撞到树木、靶子角色受到阻碍后停止移动
时间变化天空盒和光照s
按下鼠标左键角色在射击位置上,允许射击,箭矢数目大于0弩箭开始蓄力
长按鼠标左键弩箭准备蓄力拉力不断加大直到达到上限
松开鼠标左键弩箭射击
按下鼠标右键并拖动角色视角拖动
箭矢涉及到靶子上依据射击到的靶子颜色,添加相应的分数

项目资源

  • 代码(本次受到文件大小限制,只传上去了assets文件夹)

MyUnity/弩箭打靶/Assets at master · BatallaCL/MyUnity (github.com)icon-default.png?t=N7T8https://github.com/BatallaCL/MyUnity/tree/master/%E5%BC%A9%E7%AE%AD%E6%89%93%E9%9D%B6/Assets

  • 视频

弩箭打靶_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV1C64y177BA/?vd_source=a74c90c9380ff3fcdf00387a285570a6

游戏展示

代码实现

1:SkyBoxControl

        天空盒切换的控制器,使得游戏场景随着时间变化不断切换。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class SBControl : MonoBehaviour
  5. {
  6. public Material[] mats;//天空盒数组
  7. private int index = 0;
  8. public int changeTime = 3 ;//更换天空盒子的秒数
  9. // Start is called before the first frame update
  10. void Start()
  11. {
  12. Debug.Log(System.DateTime.Now.Hour);
  13. InvokeRepeating("ChangeBox", 0, changeTime);
  14. }
  15. // Update is called once per frame
  16. void Update()
  17. {
  18. }
  19. public void ChangeBox()
  20. {
  21. RenderSettings.skybox = mats[index];
  22. index++;
  23. index %= mats.Length;
  24. }
  25. }

2:DayTimeControl

        时间切换(光照强度)的控制器,使得光照强度随着时间变化不断切换从而达到白天黑夜切换的效果。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class DayTime : MonoBehaviour
  5. {
  6. public float OrbitMinute = 0.1f; //太阳转一周,所需的时间设为24分钟
  7. private float AnglePerSec = 0;
  8. //Real Time
  9. [Range(0, 1440)]
  10. public float sec = 0;
  11. private float min = 0;
  12. public DefaultTime defaultTime = DefaultTime.SystemTime;
  13. public enum DefaultTime
  14. {
  15. SystemTime,
  16. Random,
  17. Preset,
  18. }
  19. public float PresetTime = 7;
  20. [Header("Only Read")]
  21. //Game Time
  22. public float GameHour = 0;
  23. public float GameMin = 0;
  24. // Start is called before the first frame update
  25. void Start()
  26. {
  27. AnglePerSec = 360 / OrbitMinute / 60;
  28. if (defaultTime == DefaultTime.SystemTime)
  29. SetTime(System.DateTime.Now.Hour);
  30. else if (defaultTime == DefaultTime.Random)
  31. SetTime(Random.Range(0, 24));
  32. else if (defaultTime == DefaultTime.Preset)
  33. SetTime(PresetTime);
  34. }
  35. // Update is called once per frame
  36. void Update()
  37. {
  38. sec += Time.deltaTime;
  39. min = sec / 60;
  40. GameHour = (int)min % OrbitMinute;
  41. GameMin = (int)sec % 60;
  42. gameObject.transform.rotation = Quaternion.Euler(SunAngle(GameHour, GameMin), -90, 0);
  43. }
  44. float SunAngle(float hour)
  45. {
  46. return 360 / OrbitMinute * hour - 90;
  47. }
  48. float SunAngle(float hour, float minute)
  49. {
  50. return 360 / OrbitMinute * hour - 90 + AnglePerSec * minute;
  51. }
  52. void SetTime(float hour)
  53. {
  54. sec = hour * 60;
  55. }
  56. }

3:CBMove

        实现了玩家控制的角色的第一人称视角的移动(WASD)和视角旋转(随鼠标旋转),使得玩家可以体验在场景中的移动和视角旋转功能。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class CBMove : MonoBehaviour
  5. {
  6. CharacterController playerController;
  7. Vector3 direction;
  8. public float speed = 1;
  9. public float jumpPower = 5;
  10. public float gravity = 7f;
  11. public float mousespeed = 5f;
  12. public float minmouseY = -45f;
  13. public float maxmouseY = 45f;
  14. float RotationY = 0f;
  15. float RotationX = 0f;
  16. public Transform agretctCamera;
  17. private Vector3 moveDirection = Vector3.zero;
  18. // Start is called before the first frame update
  19. void Start()
  20. {
  21. playerController = this.GetComponent<CharacterController>();
  22. }
  23. // Update is called once per frame
  24. void Update()
  25. {
  26. float _horizontal = Input.GetAxis("Horizontal");
  27. float _vertical = Input.GetAxis("Vertical");
  28. if (playerController.isGrounded)
  29. {
  30. direction = new Vector3(_horizontal, 0, _vertical);
  31. if (Input.GetKeyDown(KeyCode.Space))
  32. direction.y = jumpPower;
  33. }
  34. direction.y -= gravity * Time.deltaTime;
  35. playerController.Move(playerController.transform.TransformDirection(direction * Time.deltaTime * speed));
  36. RotationX += agretctCamera.transform.localEulerAngles.y + Input.GetAxis("Mouse X") * mousespeed;
  37. RotationY -= Input.GetAxis("Mouse Y") * mousespeed;
  38. RotationY = Mathf.Clamp(RotationY, minmouseY, maxmouseY);
  39. this.transform.eulerAngles = new Vector3(0, RotationX, 0);
  40. agretctCamera.transform.eulerAngles = new Vector3(RotationY, RotationX, 0);
  41. }
  42. }

4:FireControl

        实现了弩箭的射击动作事件(左键)和弩箭角度调整(右键),是游戏玩法的核心代码。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class FireControl : MonoBehaviour
  5. {
  6. public bool fire_permisssion = true;
  7. public int arrow_num = 10;
  8. public ArrowControl arrow; //箭模板
  9. public Animator animator; //动画组件
  10. public Transform arrowPoint; //发射箭点
  11. public Transform bow_tem; //弓箭模板
  12. public Transform bow; //弓箭竖直
  13. public Transform bow_ro; //弓箭水平
  14. public float bow_rato = .1f; //竖直旋转速度
  15. public float ro_rato = .1f; //水平旋转速度
  16. public float hold_power; //蓄力强度
  17. public AnimationCurve hold_curve; //蓄力强度变化曲线
  18. public Vector3 mouse_position; //鼠标位置
  19. // Start is called before the first frame update
  20. void Start()
  21. {
  22. animator = bow_tem.GetComponent<Animator>();
  23. }
  24. // Update is called once per frame
  25. void Update()
  26. { if(fire_permisssion == true && arrow_num>0)
  27. //if(true)
  28. {
  29. //弓箭发射事件 左键控制 点下长按蓄力 松开后发射
  30. if (Input.GetKeyDown(KeyCode.Mouse0))
  31. {
  32. hold_power = 0;
  33. animator.SetBool("pull", true);
  34. }
  35. if (Input.GetKey(KeyCode.Mouse0))
  36. {
  37. animator.SetBool("hold", true);
  38. if (Time.deltaTime <= 3)
  39. {
  40. hold_power += Time.deltaTime;
  41. animator.SetFloat("hold_power", 0.7f - hold_power);
  42. }
  43. }
  44. if (Input.GetKeyUp(KeyCode.Mouse0))
  45. {
  46. animator.SetBool("pull", false);
  47. animator.SetBool("hold", false);
  48. animator.SetBool("shoot", true);
  49. ArrowControl temp = Instantiate(arrow, arrowPoint.position, arrowPoint.rotation);
  50. temp.force = hold_curve.Evaluate(hold_power);
  51. animator.SetBool("shoot", false);
  52. animator.SetFloat("hold_power", 0.5f);
  53. arrow_num--;
  54. }
  55. }
  56. //弓箭视角变化
  57. if(Input.GetKeyDown (KeyCode.Mouse1))
  58. {
  59. mouse_position = Input.mousePosition;
  60. }
  61. if (Input.GetKey(KeyCode.Mouse1))
  62. {
  63. bow_ro.Rotate( - Vector3.up * (mouse_position - Input.mousePosition).x * ro_rato);
  64. bow.Rotate(Vector3.right*(mouse_position - Input.mousePosition).y * bow_rato);
  65. }
  66. mouse_position = Input.mousePosition;
  67. }
  68. }

5:RingController

        在箭矢射击到靶子后,通过碰撞检测事件实现箭矢碰撞后的停止、玩家分数的增加、箭矢的减少。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. public class RingController : MonoBehaviour
  5. {
  6. //当前环的分值
  7. public int RingScore = 0;
  8. public ScoreRecorder sc_recorder;
  9. // Start is called before the first frame update
  10. void Start()
  11. {
  12. }
  13. // Update is called once per frame
  14. void Update()
  15. {
  16. }
  17. //碰撞检测,如果箭击中该环,就响应。
  18. void OnTriggerEnter(Collider temp)
  19. {
  20. //得到箭身
  21. Transform arrow = temp.gameObject.transform;
  22. if (temp == null)
  23. {
  24. return;
  25. }
  26. //有箭中靶
  27. if (temp.tag == "arrow")
  28. {
  29. //将箭的速度设为0
  30. arrow.GetComponent<Rigidbody>().velocity = new Vector3(0, 0, 0);
  31. //使用运动学运动控制
  32. arrow.GetComponent<Rigidbody>().isKinematic = true;
  33. }
  34. }
  35. void OnTriggerExit(Collider temp){
  36. //得到箭身
  37. Transform arrow = temp.gameObject.transform;
  38. if(temp == null)
  39. {
  40. return ;
  41. }
  42. //有箭中靶
  43. if(temp.tag == "arrow"){
  44. //将箭的速度设为0
  45. arrow.GetComponent<Rigidbody>().velocity = new Vector3(0,0,0);
  46. //使用运动学运动控制
  47. arrow.GetComponent<Rigidbody>().isKinematic = true;
  48. //计分
  49. sc_recorder.RecordScore(RingScore);
  50. //标记箭为中靶
  51. //arrow.tag = "onTarget";
  52. }
  53. }
  54. }

6:ScoreRecorder

        显示游戏的状态,包括分数、射击状态。箭矢剩余数目。

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. public class ScoreRecorder : MonoBehaviour
  6. {
  7. public FireControl A;
  8. public int score;
  9. public Text scoreText; //显示分数UI
  10. public Text fireText; //显示射击状态UI
  11. public Text arrowNumText; //显示弓箭数量UI
  12. // Start is called before the first frame update
  13. void Start()
  14. {
  15. score = 0;
  16. }
  17. private void Update()
  18. {
  19. if((A.transform.position.x>=20 && A.transform.position.x <= 70) && (A.transform.position.z>=10 && A.transform.position.z<=25))
  20. //if(true)
  21. {
  22. A.fire_permisssion = true;
  23. fireText.text = "射击:允许";
  24. arrowNumText.text = "次数:"+A.arrow_num;
  25. }
  26. else
  27. {
  28. A.fire_permisssion = false;
  29. fireText.text = "射击:禁止";
  30. arrowNumText.text = "次数:" + A.arrow_num;
  31. }
  32. }
  33. // Update is called once per frame
  34. public void RecordScore(int ringscore)
  35. {
  36. //增加新的值
  37. score += ringscore;
  38. scoreText.text = "分数:" + score;
  39. }
  40. }

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

闽ICP备14008679号