1. using UnityEngine;
  2.  
  3. namespace Complete
  4. {
  5. public class CameraControl : MonoBehaviour
  6. {
  7. /// <summary>
  8. /// 相机重新聚焦的时间
  9. /// </summary>
  10. public float m_DampTime = 0.2f;
  11. /// <summary>
  12. ///
  13. /// </summary>
  14. public float m_ScreenEdgeBuffer = 4f;
  15. /// <summary>
  16. /// 正交模式吓的最小视口大小
  17. /// </summary>
  18. public float m_MinSize = 6.5f;
  19. /// <summary>
  20. /// 相机需要保卫的目标数组
  21. /// </summary>
  22. [HideInInspector] public Transform[] m_Targets;
  23.  
  24. /// <summary>
  25. /// 相机
  26. /// </summary>
  27. private Camera m_Camera;
  28. /// <summary>
  29. /// 变焦速度
  30. /// </summary>
  31. private float m_ZoomSpeed;
  32. /// <summary>
  33. /// 移动速度
  34. /// </summary>
  35. private Vector3 m_MoveVelocity;
  36. /// <summary>
  37. /// 目标位置
  38. /// </summary>
  39. private Vector3 m_DesiredPosition;
  40.  
  41. private void Awake ()
  42. {
  43. m_Camera = GetComponentInChildren<Camera> ();
  44. }
  45.  
  46. private void FixedUpdate ()
  47. {
  48. Move ();
  49. Zoom ();
  50. }
  51.  
  52. /// <summary>
  53. /// 移动
  54. /// </summary>
  55. private void Move ()
  56. {
  57. FindAveragePosition ();
  58.  
  59. transform.position = Vector3.SmoothDamp(transform.position, m_DesiredPosition, ref m_MoveVelocity, m_DampTime);
  60. }
  61.  
  62. /// <summary>
  63. /// 查找所有目标的中间位置
  64. /// </summary>
  65. private void FindAveragePosition ()
  66. {
  67. Vector3 averagePos = new Vector3 ();
  68. ;
  69.  
  70. ; i < m_Targets.Length; i++)
  71. {
  72. if (!m_Targets[i].gameObject.activeSelf)
  73. continue;
  74.  
  75. averagePos += m_Targets[i].position;
  76. numTargets++;
  77. }
  78.  
  79. )
  80. averagePos /= numTargets;
  81.  
  82. averagePos.y = transform.position.y;
  83. m_DesiredPosition = averagePos;
  84. }
  85.  
  86. /// <summary>
  87. /// 变焦
  88. /// </summary>
  89. private void Zoom ()
  90. {
  91. float requiredSize = FindRequiredSize();
  92. m_Camera.orthographicSize = Mathf.SmoothDamp (m_Camera.orthographicSize, requiredSize, ref m_ZoomSpeed, m_DampTime);
  93. }
  94.  
  95. /// <summary>
  96. /// 查找需要的视口大小
  97. /// </summary>
  98. /// <returns></returns>
  99. private float FindRequiredSize ()
  100. {
  101.  
  102. Vector3 desiredLocalPos = transform.InverseTransformPoint(m_DesiredPosition);
  103.  
  104. float size = 0f;
  105.  
  106. ; i < m_Targets.Length; i++)
  107. {
  108. if (!m_Targets[i].gameObject.activeSelf)
  109. continue;
  110.  
  111. Vector3 targetLocalPos = transform.InverseTransformPoint(m_Targets[i].position);
  112.  
  113. Vector3 desiredPosToTarget = targetLocalPos - desiredLocalPos;
  114.  
  115. size = Mathf.Max(size, Mathf.Abs(desiredPosToTarget.y));
  116.  
  117. size = Mathf.Max(size, Mathf.Abs(desiredPosToTarget.x) / m_Camera.aspect);
  118. }
  119.  
  120. size += m_ScreenEdgeBuffer;
  121.  
  122. size = Mathf.Max (size, m_MinSize);
  123.  
  124. return size;
  125. }
  126.  
  127. /// <summary>
  128. /// 设置相机的起始位置和大小
  129. /// </summary>
  130. public void SetStartPositionAndSize ()
  131. {
  132. FindAveragePosition ();
  133.  
  134. transform.position = m_DesiredPosition;
  135.  
  136. m_Camera.orthographicSize = FindRequiredSize ();
  137. }
  138. }
  139. }

CameraControl

  1. using System.Collections;
  2. using UnityEngine;
  3. using UnityEngine.SceneManagement;
  4. using UnityEngine.UI;
  5.  
  6. namespace Complete
  7. {
  8. public class GameManager : MonoBehaviour
  9. {
  10. /// <summary>
  11. /// 要赢得游戏的局数
  12. /// </summary>
  13. ;
  14. /// <summary>
  15. /// 从回合准备转换到回合开始的时间
  16. /// </summary>
  17. public float m_StartDelay = 3f;
  18. /// <summary>
  19. /// 从回合开始转换到回合结束的时间
  20. /// </summary>
  21. public float m_EndDelay = 3f;
  22. /// <summary>
  23. /// 摄像机控制
  24. /// </summary>
  25. public CameraControl m_CameraControl;
  26. /// <summary>
  27. /// 消息文本
  28. /// </summary>
  29. public Text m_MessageText;
  30. /// <summary>
  31. /// 坦克预设
  32. /// </summary>
  33. public GameObject m_TankPrefab;
  34. /// <summary>
  35. /// 坦克管理数组
  36. /// </summary>
  37. public TankManager[] m_Tanks;
  38.  
  39. /// <summary>
  40. /// 当前回合数
  41. /// </summary>
  42. private int m_RoundNumber;
  43. /// <summary>
  44. /// 回合开始后的等待时间
  45. /// </summary>
  46. private WaitForSeconds m_StartWait;
  47. /// <summary>
  48. /// 回合结束后的等待时间
  49. /// </summary>
  50. private WaitForSeconds m_EndWait;
  51. /// <summary>
  52. /// 回合获胜者
  53. /// </summary>
  54. private TankManager m_RoundWinner;
  55. /// <summary>
  56. /// 游戏获胜者
  57. /// </summary>
  58. private TankManager m_GameWinner;
  59.  
  60. private void Start()
  61. {
  62. m_StartWait = new WaitForSeconds (m_StartDelay);
  63. m_EndWait = new WaitForSeconds (m_EndDelay);
  64.  
  65. SpawnAllTanks();
  66. SetCameraTargets();
  67.  
  68. //开启游戏主循环协程
  69. StartCoroutine (GameLoop ());
  70. }
  71.  
  72. /// <summary>
  73. /// 孵化所有坦克
  74. /// </summary>
  75. private void SpawnAllTanks()
  76. {
  77. ; i < m_Tanks.Length; i++)
  78. {
  79. m_Tanks[i].m_Instance =
  80. Instantiate(m_TankPrefab, m_Tanks[i].m_SpawnPoint.position, m_Tanks[i].m_SpawnPoint.rotation) as GameObject;
  81. m_Tanks[i].m_PlayerNumber = i + ;
  82. m_Tanks[i].Setup();
  83. }
  84. }
  85.  
  86. /// <summary>
  87. /// 设置相机目标
  88. /// </summary>
  89. private void SetCameraTargets()
  90. {
  91. Transform[] targets = new Transform[m_Tanks.Length];
  92.  
  93. ; i < targets.Length; i++)
  94. {
  95. targets[i] = m_Tanks[i].m_Instance.transform;
  96. }
  97.  
  98. m_CameraControl.m_Targets = targets;
  99. }
  100.  
  101. /// <summary>
  102. /// 游戏循环协程
  103. /// </summary>
  104. /// <returns></returns>
  105. private IEnumerator GameLoop ()
  106. {
  107. yield return StartCoroutine (RoundStarting ());
  108.  
  109. yield return StartCoroutine (RoundPlaying());
  110.  
  111. yield return StartCoroutine (RoundEnding());
  112.  
  113. if (m_GameWinner != null)
  114. {
  115. SceneManager.LoadScene ();
  116. }
  117. else
  118. {
  119. StartCoroutine (GameLoop ());
  120. }
  121. }
  122.  
  123. /// <summary>
  124. /// 回合准备协程
  125. /// </summary>
  126. /// <returns></returns>
  127. private IEnumerator RoundStarting ()
  128. {
  129. ResetAllTanks ();
  130. DisableTankControl ();
  131.  
  132. m_CameraControl.SetStartPositionAndSize ();
  133.  
  134. m_RoundNumber++;
  135. m_MessageText.text = "ROUND " + m_RoundNumber;
  136.  
  137. yield return m_StartWait;
  138. }
  139.  
  140. /// <summary>
  141. /// 回合开始协程
  142. /// </summary>
  143. /// <returns></returns>
  144. private IEnumerator RoundPlaying ()
  145. {
  146. EnableTankControl ();
  147.  
  148. m_MessageText.text = string.Empty;
  149.  
  150. while (!OneTankLeft())
  151. {
  152. yield return null;
  153. }
  154. }
  155.  
  156. /// <summary>
  157. /// 游戏结束协程
  158. /// </summary>
  159. /// <returns></returns>
  160. private IEnumerator RoundEnding ()
  161. {
  162. DisableTankControl ();
  163.  
  164. m_RoundWinner = null;
  165.  
  166. m_RoundWinner = GetRoundWinner ();
  167.  
  168. if (m_RoundWinner != null)
  169. m_RoundWinner.m_Wins++;
  170.  
  171. m_GameWinner = GetGameWinner ();
  172.  
  173. string message = EndMessage ();
  174. m_MessageText.text = message;
  175.  
  176. yield return m_EndWait;
  177. }
  178.  
  179. /// <summary>
  180. /// 检查激活的坦克数量是否小于等于1,用来设置这局游戏是否结束
  181. /// </summary>
  182. /// <returns></returns>
  183. private bool OneTankLeft()
  184. {
  185. ;
  186.  
  187. ; i < m_Tanks.Length; i++)
  188. {
  189. if (m_Tanks[i].m_Instance.activeSelf)
  190. numTanksLeft++;
  191. }
  192.  
  193. ;
  194. }
  195.  
  196. /// <summary>
  197. /// 获取每局的胜者
  198. /// </summary>
  199. /// <returns></returns>
  200. private TankManager GetRoundWinner()
  201. {
  202. ; i < m_Tanks.Length; i++)
  203. {
  204. if (m_Tanks[i].m_Instance.activeSelf)
  205. return m_Tanks[i];
  206. }
  207.  
  208. return null;
  209. }
  210.  
  211. /// <summary>
  212. /// 获取游戏的胜者
  213. /// </summary>
  214. /// <returns></returns>
  215. private TankManager GetGameWinner()
  216. {
  217. ; i < m_Tanks.Length; i++)
  218. {
  219. if (m_Tanks[i].m_Wins == m_NumRoundsToWin)
  220. return m_Tanks[i];
  221. }
  222.  
  223. return null;
  224. }
  225.  
  226. /// <summary>
  227. /// 每回合结束或游戏结束的消息
  228. /// </summary>
  229. /// <returns></returns>
  230. private string EndMessage()
  231. {
  232. //默认信息为平局
  233. string message = "DRAW!";
  234.  
  235. //有回合赢家,显示这回合谁赢了
  236. if(m_RoundWinner != null)
  237. message = m_RoundWinner.m_ColoredPlayerText + " WINS THE ROUND!";
  238.  
  239. message += "\n\n\n\n";
  240.  
  241. ; i < m_Tanks.Length; i++)
  242. {
  243. message += m_Tanks[i].m_ColoredPlayerText + ": " + m_Tanks[i].m_Wins + " WINS\n";
  244. }
  245.  
  246. if (m_GameWinner != null)
  247. message = m_GameWinner.m_ColoredPlayerText + " WINS THE GAME!";
  248.  
  249. return message;
  250. }
  251.  
  252. /// <summary>
  253. /// 重置所有坦克
  254. /// </summary>
  255. private void ResetAllTanks()
  256. {
  257. ; i < m_Tanks.Length; i++)
  258. {
  259. m_Tanks[i].Reset();
  260. }
  261. }
  262.  
  263. /// <summary>
  264. /// 开启所有坦克的控制
  265. /// </summary>
  266. private void EnableTankControl()
  267. {
  268. ; i < m_Tanks.Length; i++)
  269. {
  270. m_Tanks[i].EnableControl();
  271. }
  272. }
  273.  
  274. /// <summary>
  275. /// 关闭所有坦克的控制
  276. /// </summary>
  277. private void DisableTankControl()
  278. {
  279. ; i < m_Tanks.Length; i++)
  280. {
  281. m_Tanks[i].DisableControl();
  282. }
  283. }
  284. }
  285. }

GameManager

  1. using System;
  2. using UnityEngine;
  3.  
  4. namespace Complete
  5. {
  6. [Serializable]
  7. public class TankManager
  8. {
  9. /// <summary>
  10. /// 坦克颜色
  11. /// </summary>
  12. public Color m_PlayerColor;
  13. /// <summary>
  14. /// 坦克孵化点
  15. /// </summary>
  16. public Transform m_SpawnPoint;
  17. /// <summary>
  18. /// 玩家编号
  19. /// </summary>
  20. [HideInInspector] public int m_PlayerNumber;
  21. /// <summary>
  22. /// 包含颜色的代表玩家的字符串
  23. /// </summary>
  24. [HideInInspector] public string m_ColoredPlayerText;
  25. /// <summary>
  26. /// 坦克实例的引用
  27. /// </summary>
  28. [HideInInspector] public GameObject m_Instance;
  29. /// <summary>
  30. /// 玩家已赢得的局数
  31. /// </summary>
  32. [HideInInspector] public int m_Wins;
  33.  
  34. /// <summary>
  35. /// 坦克移动
  36. /// </summary>
  37. private TankMovement m_Movement;
  38. /// <summary>
  39. /// 坦克射击
  40. /// </summary>
  41. private TankShooting m_Shooting;
  42. /// <summary>
  43. /// 坦克游戏物体上的canvas
  44. /// </summary>
  45. private GameObject m_CanvasGameObject;
  46.  
  47. /// <summary>
  48. /// 设置坦克
  49. /// </summary>
  50. public void Setup ()
  51. {
  52.  
  53. m_Movement = m_Instance.GetComponent<TankMovement> ();
  54. m_Shooting = m_Instance.GetComponent<TankShooting> ();
  55. m_CanvasGameObject = m_Instance.GetComponentInChildren<Canvas> ().gameObject;
  56.  
  57. m_Movement.m_PlayerNumber = m_PlayerNumber;
  58. m_Shooting.m_PlayerNumber = m_PlayerNumber;
  59.  
  60. //设置带颜色的玩家名
  61. m_ColoredPlayerText = "<color=#" + ColorUtility.ToHtmlStringRGB(m_PlayerColor) + ">PLAYER " + m_PlayerNumber + "</color>";
  62.  
  63. //获取并设置坦克及子物体的颜色
  64. MeshRenderer[] renderers = m_Instance.GetComponentsInChildren<MeshRenderer> ();
  65.  
  66. ; i < renderers.Length; i++)
  67. {
  68. renderers[i].material.color = m_PlayerColor;
  69. }
  70. }
  71.  
  72. /// <summary>
  73. /// 关闭控制
  74. /// </summary>
  75. public void DisableControl ()
  76. {
  77. m_Movement.enabled = false;
  78. m_Shooting.enabled = false;
  79.  
  80. m_CanvasGameObject.SetActive (false);
  81. }
  82.  
  83. /// <summary>
  84. /// 开启控制
  85. /// </summary>
  86. public void EnableControl ()
  87. {
  88. m_Movement.enabled = true;
  89. m_Shooting.enabled = true;
  90.  
  91. m_CanvasGameObject.SetActive (true);
  92. }
  93.  
  94. /// <summary>
  95. /// 重置坦克状态
  96. /// </summary>
  97. public void Reset ()
  98. {
  99. m_Instance.transform.position = m_SpawnPoint.position;
  100. m_Instance.transform.rotation = m_SpawnPoint.rotation;
  101.  
  102. m_Instance.SetActive (false);
  103. m_Instance.SetActive (true);
  104. }
  105. }
  106. }

TankManager

  1. using UnityEngine;
  2. using UnityEngine.UI;
  3.  
  4. namespace Complete
  5. {
  6. /// <summary>
  7. /// 坦克生命
  8. /// </summary>
  9. public class TankHealth : MonoBehaviour
  10. {
  11. /// <summary>
  12. /// 初始坦克生命
  13. /// </summary>
  14. public float m_StartingHealth = 100f;
  15. /// <summary>
  16. /// 血量滑动条
  17. /// </summary>
  18. public Slider m_Slider;
  19. /// <summary>
  20. /// 血量滑动条的图片
  21. /// </summary>
  22. public Image m_FillImage;
  23. /// <summary>
  24. /// 坦克满血的滑动条颜色
  25. /// </summary>
  26. public Color m_FullHealthColor = Color.green;
  27. /// <summary>
  28. /// 坦克没血的滑动条颜色
  29. /// </summary>
  30. public Color m_ZeroHealthColor = Color.red;
  31. /// <summary>
  32. /// 坦克爆炸的预设
  33. /// </summary>
  34. public GameObject m_ExplosionPrefab;
  35.  
  36. /// <summary>
  37. /// 坦克爆炸的音效
  38. /// </summary>
  39. private AudioSource m_ExplosionAudio;
  40. /// <summary>
  41. /// 坦克爆炸的粒子系统
  42. /// </summary>
  43. private ParticleSystem m_ExplosionParticles;
  44. /// <summary>
  45. /// 坦克当前的血量
  46. /// </summary>
  47. private float m_CurrentHealth;
  48. /// <summary>
  49. /// 坦克是否死亡
  50. /// </summary>
  51. private bool m_Dead;
  52.  
  53. private void Awake ()
  54. {
  55. //实例化爆炸预设并获取爆炸粒子系统的引用
  56. m_ExplosionParticles = Instantiate (m_ExplosionPrefab).GetComponent<ParticleSystem> ();
  57.  
  58. //获取爆炸的音效
  59. m_ExplosionAudio = m_ExplosionParticles.GetComponent<AudioSource> ();
  60.  
  61. //禁用爆炸粒子系统
  62. m_ExplosionParticles.gameObject.SetActive (false);
  63. }
  64.  
  65. private void OnEnable()
  66. {
  67. //设置当前血量为起始血量
  68. m_CurrentHealth = m_StartingHealth;
  69. //设置死亡标志位为false
  70. m_Dead = false;
  71.  
  72. //修改血量UI
  73. SetHealthUI();
  74. }
  75.  
  76. /// <summary>
  77. /// 坦克受到伤害
  78. /// </summary>
  79. /// <param name="amount"></param>
  80. public void TakeDamage (float amount)
  81. {
  82. //修改当前血量
  83. m_CurrentHealth -= amount;
  84.  
  85. //修改血量UI
  86. SetHealthUI ();
  87.  
  88. //如果死亡,当前血量<=0
  89. if (m_CurrentHealth <= 0f && !m_Dead)
  90. {
  91. OnDeath ();
  92. }
  93. }
  94.  
  95. /// <summary>
  96. /// 设置坦克血量UI
  97. /// </summary>
  98. private void SetHealthUI ()
  99. {
  100. //设置滑动条的值为当前血量
  101. m_Slider.value = m_CurrentHealth;
  102.  
  103. //根据当前血量和起始血量的比值设置坦克的滑动条血量的颜色
  104. m_FillImage.color = Color.Lerp (m_ZeroHealthColor, m_FullHealthColor, m_CurrentHealth / m_StartingHealth);
  105. }
  106.  
  107. /// <summary>
  108. /// 坦克死亡
  109. /// </summary>
  110. private void OnDeath ()
  111. {
  112. //设置死亡标志位 true
  113. m_Dead = true;
  114.  
  115. //将爆炸粒子系统的位置移动到坦克的位置
  116. m_ExplosionParticles.transform.position = transform.position;
  117. m_ExplosionParticles.gameObject.SetActive (true);
  118.  
  119. //播放爆炸粒子系统
  120. m_ExplosionParticles.Play ();
  121.  
  122. //播放爆炸音效
  123. m_ExplosionAudio.Play();
  124.  
  125. //禁用坦克
  126. gameObject.SetActive (false);
  127. }
  128. }
  129. }

TankHealth

  1. using UnityEngine;
  2.  
  3. namespace Complete
  4. {
  5. /// <summary>
  6. /// 坦克移动
  7. /// </summary>
  8. public class TankMovement : MonoBehaviour
  9. {
  10. /// <summary>
  11. /// 玩家编号
  12. /// </summary>
  13. ;
  14. /// <summary>
  15. /// 坦克的移动速度
  16. /// </summary>
  17. public float m_Speed = 12f;
  18. /// <summary>
  19. /// 坦克的转向速度
  20. /// </summary>
  21. public float m_TurnSpeed = 180f;
  22. /// <summary>
  23. /// 移动声源
  24. /// </summary>
  25. public AudioSource m_MovementAudio;
  26. /// <summary>
  27. /// 空闲时的声音
  28. /// </summary>
  29. public AudioClip m_EngineIdling;
  30. /// <summary>
  31. /// 移动时的声音
  32. /// </summary>
  33. public AudioClip m_EngineDriving;
  34. /// <summary>
  35. /// 音高范围
  36. /// </summary>
  37. public float m_PitchRange = 0.2f;
  38.  
  39. /// <summary>
  40. /// 控制前后移动的轴名
  41. /// </summary>
  42. private string m_MovementAxisName;
  43. /// <summary>
  44. /// 控制
  45. /// </summary>
  46. private string m_TurnAxisName;
  47. /// <summary>
  48. /// 刚体
  49. /// </summary>
  50. private Rigidbody m_Rigidbody;
  51.  
  52. /// <summary>
  53. /// 移动输入
  54. /// </summary>
  55. private float m_MovementInputValue;
  56. /// <summary>
  57. /// 转向输入
  58. /// </summary>
  59. private float m_TurnInputValue;
  60. /// <summary>
  61. /// 原始音高
  62. /// </summary>
  63. private float m_OriginalPitch;
  64.  
  65. private void Awake ()
  66. {
  67. m_Rigidbody = GetComponent<Rigidbody> ();
  68. }
  69.  
  70. private void OnEnable ()
  71. {
  72.  
  73. m_Rigidbody.isKinematic = false;
  74.  
  75. m_MovementInputValue = 0f;
  76. m_TurnInputValue = 0f;
  77. }
  78.  
  79. private void OnDisable ()
  80. {
  81. m_Rigidbody.isKinematic = true;
  82. }
  83.  
  84. private void Start ()
  85. {
  86. //通过玩家编号获取输入轴
  87. m_MovementAxisName = "Vertical" + m_PlayerNumber;
  88. m_TurnAxisName = "Horizontal" + m_PlayerNumber;
  89.  
  90. //存储原始音高
  91. m_OriginalPitch = m_MovementAudio.pitch;
  92. }
  93.  
  94. private void Update ()
  95. {
  96. //获取输入轴的值
  97. m_MovementInputValue = Input.GetAxis (m_MovementAxisName);
  98. m_TurnInputValue = Input.GetAxis (m_TurnAxisName);
  99.  
  100. EngineAudio ();
  101. }
  102.  
  103. /// <summary>
  104. /// 处理引擎的声音
  105. /// </summary>
  106. private void EngineAudio ()
  107. {
  108. //如果没有输入
  109. if (Mathf.Abs (m_MovementInputValue) < 0.1f && Mathf.Abs (m_TurnInputValue) < 0.1f)
  110. {
  111. //如果正在播放移动的声音
  112. if (m_MovementAudio.clip == m_EngineDriving)
  113. {
  114. //播放闲置的声音
  115. m_MovementAudio.clip = m_EngineIdling;
  116. m_MovementAudio.pitch = Random.Range (m_OriginalPitch - m_PitchRange, m_OriginalPitch + m_PitchRange);
  117. m_MovementAudio.Play ();
  118. }
  119. }
  120. //如果有输入
  121. else
  122. {
  123. //如果正在播放闲置的声音
  124. if (m_MovementAudio.clip == m_EngineIdling)
  125. {
  126. //播放移动的声音
  127. m_MovementAudio.clip = m_EngineDriving;
  128. m_MovementAudio.pitch = Random.Range(m_OriginalPitch - m_PitchRange, m_OriginalPitch + m_PitchRange);
  129. m_MovementAudio.Play();
  130. }
  131. }
  132. }
  133.  
  134. private void FixedUpdate ()
  135. {
  136. //移动
  137. Move ();
  138. //旋转
  139. Turn ();
  140. }
  141.  
  142. /// <summary>
  143. /// 移动
  144. /// </summary>
  145. private void Move ()
  146. {
  147. //创建一个坦克的速度向量
  148. Vector3 movement = transform.forward * m_MovementInputValue * m_Speed * Time.deltaTime;
  149.  
  150. //刚体移动
  151. m_Rigidbody.MovePosition(m_Rigidbody.position + movement);
  152. }
  153.  
  154. /// <summary>
  155. /// 旋转
  156. /// </summary>
  157. private void Turn ()
  158. {
  159. //根据输入,旋转速度以及每帧的时间计算旋转的值
  160. float turn = m_TurnInputValue * m_TurnSpeed * Time.deltaTime;
  161.  
  162. //创建y轴的四元数旋转
  163. Quaternion turnRotation = Quaternion.Euler (0f, turn, 0f);
  164.  
  165. //刚体旋转
  166. m_Rigidbody.MoveRotation (m_Rigidbody.rotation * turnRotation);
  167. }
  168. }
  169. }

TankMovement

  1. using UnityEngine;
  2. using UnityEngine.UI;
  3.  
  4. namespace Complete
  5. {
  6. /// <summary>
  7. /// 坦克射击
  8. /// </summary>
  9. public class TankShooting : MonoBehaviour
  10. {
  11. /// <summary>
  12. /// 玩家编号
  13. /// </summary>
  14. ;
  15. /// <summary>
  16. /// 炮弹刚体
  17. /// </summary>
  18. public Rigidbody m_Shell;
  19. /// <summary>
  20. /// 射击的位置
  21. /// </summary>
  22. public Transform m_FireTransform;
  23. /// <summary>
  24. /// 射击的箭头滑动条
  25. /// </summary>
  26. public Slider m_AimSlider;
  27. /// <summary>
  28. /// 发射声音
  29. /// </summary>
  30. public AudioSource m_ShootingAudio;
  31. /// <summary>
  32. /// 充能声音
  33. /// </summary>
  34. public AudioClip m_ChargingClip;
  35. /// <summary>
  36. /// 开火声音
  37. /// </summary>
  38. public AudioClip m_FireClip;
  39. /// <summary>
  40. /// 发射炮弹最小的力
  41. /// </summary>
  42. public float m_MinLaunchForce = 15f;
  43. /// <summary>
  44. /// 发射炮弹最大的力
  45. /// </summary>
  46. public float m_MaxLaunchForce = 30f;
  47. /// <summary>
  48. /// 发射炮弹的最大充能时间
  49. /// </summary>
  50. public float m_MaxChargeTime = 0.75f;
  51.  
  52. /// <summary>
  53. /// 控制发射的轴名
  54. /// </summary>
  55. private string m_FireButton;
  56. /// <summary>
  57. /// 当前的发射力
  58. /// </summary>
  59. private float m_CurrentLaunchForce;
  60. /// <summary>
  61. /// 充能速度
  62. /// </summary>
  63. private float m_ChargeSpeed;
  64. /// <summary>
  65. /// 是否已发射
  66. /// </summary>
  67. private bool m_Fired;
  68.  
  69. private void OnEnable()
  70. {
  71. //重置当前发射力和箭头滑动条的值
  72. m_CurrentLaunchForce = m_MinLaunchForce;
  73. m_AimSlider.value = m_MinLaunchForce;
  74. }
  75.  
  76. private void Start ()
  77. {
  78. //根据玩家编号设置 发射的轴名
  79. m_FireButton = "Fire" + m_PlayerNumber;
  80.  
  81. //计算发射充能
  82. m_ChargeSpeed = (m_MaxLaunchForce - m_MinLaunchForce) / m_MaxChargeTime;
  83. }
  84.  
  85. private void Update ()
  86. {
  87. //设置箭头滑动条的值
  88. m_AimSlider.value = m_MinLaunchForce;
  89.  
  90. //如果当前的发射力大于最大发射力,并且没有发射
  91. if (m_CurrentLaunchForce >= m_MaxLaunchForce && !m_Fired)
  92. {
  93. //用最大发射力发射
  94. m_CurrentLaunchForce = m_MaxLaunchForce;
  95. Fire ();
  96. }
  97. //如果按下了发射按钮
  98. else if (Input.GetButtonDown (m_FireButton))
  99. {
  100. //设置发射标志位为false
  101. m_Fired = false;
  102. //设置当前发射力为最小力
  103. m_CurrentLaunchForce = m_MinLaunchForce;
  104.  
  105. //播放充能声音
  106. m_ShootingAudio.clip = m_ChargingClip;
  107. m_ShootingAudio.Play ();
  108. }
  109. //如果发射按钮被按住且炮弹并没有发射
  110. else if (Input.GetButton (m_FireButton) && !m_Fired)
  111. {
  112. //更新当前发射力
  113. m_CurrentLaunchForce += m_ChargeSpeed * Time.deltaTime;
  114. //更新箭头滑动条的值
  115. m_AimSlider.value = m_CurrentLaunchForce;
  116. }
  117. //如果发射键松开且炮弹没有发射
  118. else if (Input.GetButtonUp (m_FireButton) && !m_Fired)
  119. {
  120. //发射炮弹
  121. Fire ();
  122. }
  123. }
  124.  
  125. /// <summary>
  126. /// 发射
  127. /// </summary>
  128. private void Fire ()
  129. {
  130. //设置发射标志位
  131. m_Fired = true;
  132.  
  133. //获取炮弹刚体的引用
  134. Rigidbody shellInstance =
  135. Instantiate (m_Shell, m_FireTransform.position, m_FireTransform.rotation) as Rigidbody;
  136.  
  137. //设置刚体的速度
  138. shellInstance.velocity = m_CurrentLaunchForce * m_FireTransform.forward;
  139.  
  140. //播放发射声音
  141. m_ShootingAudio.clip = m_FireClip;
  142. m_ShootingAudio.Play ();
  143.  
  144. //重置当前发射力为最小发射力
  145. m_CurrentLaunchForce = m_MinLaunchForce;
  146. }
  147. }
  148. }

TankShooting

  1. using UnityEngine;
  2.  
  3. namespace Complete
  4. {
  5. /// <summary>
  6. /// 炮弹爆炸
  7. /// </summary>
  8. public class ShellExplosion : MonoBehaviour
  9. {
  10. /// <summary>
  11. /// 坦克层
  12. /// </summary>
  13. public LayerMask m_TankMask;
  14. public ParticleSystem m_ExplosionParticles;
  15. /// <summary>
  16. /// 爆炸声源
  17. /// </summary>
  18. public AudioSource m_ExplosionAudio;
  19. /// <summary>
  20. /// 最大伤害
  21. /// </summary>
  22. public float m_MaxDamage = 100f;
  23. /// <summary>
  24. /// 爆炸力
  25. /// </summary>
  26. public float m_ExplosionForce = 1000f;
  27. /// <summary>
  28. /// 炮弹的生命周期
  29. /// </summary>
  30. public float m_MaxLifeTime = 2f;
  31. /// <summary>
  32. /// 爆炸半径
  33. /// </summary>
  34. public float m_ExplosionRadius = 5f;
  35.  
  36. private void Start ()
  37. {
  38. //如果炸弹没有被销毁,经过指定时间后自动销毁
  39. Destroy (gameObject, m_MaxLifeTime);
  40. }
  41.  
  42. private void OnTriggerEnter (Collider other)
  43. {
  44. //以炮弹为中心,爆炸半径为半径发射相交球
  45. Collider[] colliders = Physics.OverlapSphere (transform.position, m_ExplosionRadius, m_TankMask);
  46.  
  47. //循环遍历碰撞体
  48. ; i < colliders.Length; i++)
  49. {
  50. //获取目标刚体
  51. Rigidbody targetRigidbody = colliders[i].GetComponent<Rigidbody> ();
  52.  
  53. //如果没有刚体,则继续检测下一个
  54. if (!targetRigidbody)
  55. continue;
  56.  
  57. //目标刚体添加爆炸力
  58. targetRigidbody.AddExplosionForce (m_ExplosionForce, transform.position, m_ExplosionRadius);
  59.  
  60. //获取目标的血量
  61. TankHealth targetHealth = targetRigidbody.GetComponent<TankHealth> ();
  62.  
  63. //如果没有,检测下一个
  64. if (!targetHealth)
  65. continue;
  66.  
  67. //根据目标位置计算伤害
  68. float damage = CalculateDamage (targetRigidbody.position);
  69.  
  70. //目标受到伤害
  71. targetHealth.TakeDamage (damage);
  72. }
  73.  
  74. m_ExplosionParticles.transform.parent = null;
  75.  
  76. //播放爆炸粒子效果
  77. m_ExplosionParticles.Play();
  78.  
  79. //播放爆炸声音
  80. m_ExplosionAudio.Play();
  81.  
  82. //定时销毁粒子系统
  83. Destroy (m_ExplosionParticles.gameObject, m_ExplosionParticles.duration);
  84.  
  85. //销毁炮弹
  86. Destroy (gameObject);
  87. }
  88.  
  89. /// <summary>
  90. /// 计算伤害
  91. /// </summary>
  92. /// <param name="targetPosition">目标位置</param>
  93. /// <returns></returns>
  94. private float CalculateDamage (Vector3 targetPosition)
  95. {
  96. //创建一个从自身到目标的向量
  97. Vector3 explosionToTarget = targetPosition - transform.position;
  98.  
  99. //计算这个向量的模
  100. float explosionDistance = explosionToTarget.magnitude;
  101.  
  102. //计算相对距离
  103. float relativeDistance = (m_ExplosionRadius - explosionDistance) / m_ExplosionRadius;
  104.  
  105. //根据距离比例和最大伤害计算伤害
  106. float damage = relativeDistance * m_MaxDamage;
  107.  
  108. //确保最小伤害为0
  109. damage = Mathf.Max (0f, damage);
  110.  
  111. return damage;
  112. }
  113. }
  114. }

ShellExplosion

  1. using UnityEngine;
  2.  
  3. namespace Complete
  4. {
  5. /// <summary>
  6. /// UI朝向控制
  7. /// </summary>
  8. public class UIDirectionControl : MonoBehaviour
  9. {
  10. /// <summary>
  11. /// 是否使用相对旋转
  12. /// </summary>
  13. public bool m_UseRelativeRotation = true;
  14.  
  15. /// <summary>
  16. /// 局部旋转
  17. /// </summary>
  18. private Quaternion m_RelativeRotation;
  19.  
  20. private void Start ()
  21. {
  22. //局部旋转为父对象的局部旋转
  23. m_RelativeRotation = transform.parent.localRotation;
  24. }
  25.  
  26. private void Update ()
  27. {
  28. if (m_UseRelativeRotation)
  29. transform.rotation = m_RelativeRotation;
  30. }
  31. }
  32. }

UIDirectionControl

视频:https://pan.baidu.com/s/1eRFbQYA

项目:https://pan.baidu.com/s/1midmmuc

Tanks!Tutorial 学习的更多相关文章

  1. Python Tutorial 学习(八)--Errors and Exceptions

    Python Tutorial 学习(八)--Errors and Exceptions恢复 Errors and Exceptions 错误与异常 此前,我们还没有开始着眼于错误信息.不过如果你是一 ...

  2. Django 1.7 Tutorial 学习笔记

    官方教程在这里 : Here 写在前面的废话:)) 以前学习新东西,第一想到的是找本入门教程,按照书上做一遍.现在看了各种网上的入门教程后,我觉得还是看官方Tutorial靠谱.书的弊端一说一大推 本 ...

  3. 深度学习 Deep Learning UFLDL 最新 Tutorial 学习笔记 1:Linear Regression

    1 前言 Andrew Ng的UFLDL在2014年9月底更新了. 对于開始研究Deep Learning的童鞋们来说这真的是极大的好消息! 新的Tutorial相比旧的Tutorial添加了Conv ...

  4. SQL Expression Language Tutorial 学习笔记一

    http://docs.sqlalchemy.org/en/latest/core/tutorial.html Google 翻译了一下 SQLAlchemy Expression Language, ...

  5. FFmpeg的tutorial 学习

    一.前言: 这是一个学习 FFmpeg 的 tutorial 系列. 这个是一个对初学者比较友好的FFmpeg学习教程,作者一步步引导我们实现了一个音视频同步的播放器. 参考链接: 原文地址: htt ...

  6. Python Tutorial 学习(六)--Modules

    6. Modules 当你退出Python的shell模式然后又重新进入的时候,之前定义的变量,函数等都会没有了. 因此, 推荐的做法是将这些东西写入文件,并在适当的时候调用获取他们. 这就是为人所知 ...

  7. Python Tutorial 学习(四)--More Control Flow Tools

    4.1 if 表达式 作为最为人熟知的if.你肯定对这样的一些表达式不感到陌生: >>> x = int(raw_input("Please enter an intege ...

  8. Python Tutorial 学习(一)--Whetting Your Appetite

    Whetting Your Appetite [吊你的胃口]... 这里就直接原文奉上了... If you do much work on computers, eventually you fin ...

  9. 深度学习 Deep Learning UFLDL 最新Tutorial 学习笔记 5:Softmax Regression

    Softmax Regression Tutorial地址:http://ufldl.stanford.edu/tutorial/supervised/SoftmaxRegression/ 从本节開始 ...

随机推荐

  1. Ubuntu 修改 /etc/resolv.conf 被清空 或重启不生效解决

    sudo gedit /etc/NetworkManager/NetworkManager.conf 注释掉 dns=dnsmasq [main] plugins=ifupdown,keyfile,o ...

  2. Capjoint的merrcmd生成二次曲线的misfit原理

    http://www.personal.psu.edu/jhm/f90/lectures/lsq2.html

  3. POJ - 2823 Sliding Window (滑动窗口入门)

    An array of size n ≤ 10 6 is given to you. There is a sliding window of size kwhich is moving from t ...

  4. python random模块(获取随机数)

    如果要使用random模块,需要先导入 import random 1.random.random()  #用于生成一个0到1的随机浮点数 2.random.uniform(a,b)  #用于生成一个 ...

  5. 玩转 React 【第03期】:邂逅 React 组件

    上期回顾 前文我们讲解了 React 模板 JSX,接着我们继续来看看 React 组件又是如何工作的呢? 组件化开发到了今天已经是大家的共识,在 React 中,组件同样也是组成我们整个项目的基本单 ...

  6. 关于 数据库 my_slq的 安装及其卸载

    安装的时候 注意事项 自定后 根据电脑的系统版本 选择32  或者64  然后选择→方向键 密码默认是123456  或者  123123 查看装的数据库是否安装好了 如何完全卸载 mysql 数据库 ...

  7. day 30 客户端获取cmd 命令的步骤

    import subprocessimport structimport jsonfrom socket import *server=socket(AF_INET,SOCK_STREAM)serve ...

  8. vue 手写组件 集合

    Num.1 :  链接 向右滑动, 显示删除按钮,  根据touchStart touchEnd 的 clientX 差距 > 30; 说明是向左滑动, 显示; 改变 e.currentTarg ...

  9. kbmMWLog同时输出日志到多个日志管理器

    kbmMWLog日志框架,针对不同的业务情况,提供了多种日志管理器: TkbmMWStreamLogManager TkbmMWLocalFileLogManager TkbmMWSystemLogM ...

  10. python 26个技巧

    26个你不知道的Python技巧   Python是目前世界上最流行的编程语言之一.因为: 1.它容易学习 2.它用途超广 3.它有非常多的开源支持(大量的模块和库) 不好意思,优达菌又啰嗦了. 本文 ...