Tanks!Tutorial 学习
- using UnityEngine;
- namespace Complete
- {
- public class CameraControl : MonoBehaviour
- {
- /// <summary>
- /// 相机重新聚焦的时间
- /// </summary>
- public float m_DampTime = 0.2f;
- /// <summary>
- ///
- /// </summary>
- public float m_ScreenEdgeBuffer = 4f;
- /// <summary>
- /// 正交模式吓的最小视口大小
- /// </summary>
- public float m_MinSize = 6.5f;
- /// <summary>
- /// 相机需要保卫的目标数组
- /// </summary>
- [HideInInspector] public Transform[] m_Targets;
- /// <summary>
- /// 相机
- /// </summary>
- private Camera m_Camera;
- /// <summary>
- /// 变焦速度
- /// </summary>
- private float m_ZoomSpeed;
- /// <summary>
- /// 移动速度
- /// </summary>
- private Vector3 m_MoveVelocity;
- /// <summary>
- /// 目标位置
- /// </summary>
- private Vector3 m_DesiredPosition;
- private void Awake ()
- {
- m_Camera = GetComponentInChildren<Camera> ();
- }
- private void FixedUpdate ()
- {
- Move ();
- Zoom ();
- }
- /// <summary>
- /// 移动
- /// </summary>
- private void Move ()
- {
- FindAveragePosition ();
- transform.position = Vector3.SmoothDamp(transform.position, m_DesiredPosition, ref m_MoveVelocity, m_DampTime);
- }
- /// <summary>
- /// 查找所有目标的中间位置
- /// </summary>
- private void FindAveragePosition ()
- {
- Vector3 averagePos = new Vector3 ();
- ;
- ; i < m_Targets.Length; i++)
- {
- if (!m_Targets[i].gameObject.activeSelf)
- continue;
- averagePos += m_Targets[i].position;
- numTargets++;
- }
- )
- averagePos /= numTargets;
- averagePos.y = transform.position.y;
- m_DesiredPosition = averagePos;
- }
- /// <summary>
- /// 变焦
- /// </summary>
- private void Zoom ()
- {
- float requiredSize = FindRequiredSize();
- m_Camera.orthographicSize = Mathf.SmoothDamp (m_Camera.orthographicSize, requiredSize, ref m_ZoomSpeed, m_DampTime);
- }
- /// <summary>
- /// 查找需要的视口大小
- /// </summary>
- /// <returns></returns>
- private float FindRequiredSize ()
- {
- Vector3 desiredLocalPos = transform.InverseTransformPoint(m_DesiredPosition);
- float size = 0f;
- ; i < m_Targets.Length; i++)
- {
- if (!m_Targets[i].gameObject.activeSelf)
- continue;
- Vector3 targetLocalPos = transform.InverseTransformPoint(m_Targets[i].position);
- Vector3 desiredPosToTarget = targetLocalPos - desiredLocalPos;
- size = Mathf.Max(size, Mathf.Abs(desiredPosToTarget.y));
- size = Mathf.Max(size, Mathf.Abs(desiredPosToTarget.x) / m_Camera.aspect);
- }
- size += m_ScreenEdgeBuffer;
- size = Mathf.Max (size, m_MinSize);
- return size;
- }
- /// <summary>
- /// 设置相机的起始位置和大小
- /// </summary>
- public void SetStartPositionAndSize ()
- {
- FindAveragePosition ();
- transform.position = m_DesiredPosition;
- m_Camera.orthographicSize = FindRequiredSize ();
- }
- }
- }
CameraControl
- using System.Collections;
- using UnityEngine;
- using UnityEngine.SceneManagement;
- using UnityEngine.UI;
- namespace Complete
- {
- public class GameManager : MonoBehaviour
- {
- /// <summary>
- /// 要赢得游戏的局数
- /// </summary>
- ;
- /// <summary>
- /// 从回合准备转换到回合开始的时间
- /// </summary>
- public float m_StartDelay = 3f;
- /// <summary>
- /// 从回合开始转换到回合结束的时间
- /// </summary>
- public float m_EndDelay = 3f;
- /// <summary>
- /// 摄像机控制
- /// </summary>
- public CameraControl m_CameraControl;
- /// <summary>
- /// 消息文本
- /// </summary>
- public Text m_MessageText;
- /// <summary>
- /// 坦克预设
- /// </summary>
- public GameObject m_TankPrefab;
- /// <summary>
- /// 坦克管理数组
- /// </summary>
- public TankManager[] m_Tanks;
- /// <summary>
- /// 当前回合数
- /// </summary>
- private int m_RoundNumber;
- /// <summary>
- /// 回合开始后的等待时间
- /// </summary>
- private WaitForSeconds m_StartWait;
- /// <summary>
- /// 回合结束后的等待时间
- /// </summary>
- private WaitForSeconds m_EndWait;
- /// <summary>
- /// 回合获胜者
- /// </summary>
- private TankManager m_RoundWinner;
- /// <summary>
- /// 游戏获胜者
- /// </summary>
- private TankManager m_GameWinner;
- private void Start()
- {
- m_StartWait = new WaitForSeconds (m_StartDelay);
- m_EndWait = new WaitForSeconds (m_EndDelay);
- SpawnAllTanks();
- SetCameraTargets();
- //开启游戏主循环协程
- StartCoroutine (GameLoop ());
- }
- /// <summary>
- /// 孵化所有坦克
- /// </summary>
- private void SpawnAllTanks()
- {
- ; i < m_Tanks.Length; i++)
- {
- m_Tanks[i].m_Instance =
- Instantiate(m_TankPrefab, m_Tanks[i].m_SpawnPoint.position, m_Tanks[i].m_SpawnPoint.rotation) as GameObject;
- m_Tanks[i].m_PlayerNumber = i + ;
- m_Tanks[i].Setup();
- }
- }
- /// <summary>
- /// 设置相机目标
- /// </summary>
- private void SetCameraTargets()
- {
- Transform[] targets = new Transform[m_Tanks.Length];
- ; i < targets.Length; i++)
- {
- targets[i] = m_Tanks[i].m_Instance.transform;
- }
- m_CameraControl.m_Targets = targets;
- }
- /// <summary>
- /// 游戏循环协程
- /// </summary>
- /// <returns></returns>
- private IEnumerator GameLoop ()
- {
- yield return StartCoroutine (RoundStarting ());
- yield return StartCoroutine (RoundPlaying());
- yield return StartCoroutine (RoundEnding());
- if (m_GameWinner != null)
- {
- SceneManager.LoadScene ();
- }
- else
- {
- StartCoroutine (GameLoop ());
- }
- }
- /// <summary>
- /// 回合准备协程
- /// </summary>
- /// <returns></returns>
- private IEnumerator RoundStarting ()
- {
- ResetAllTanks ();
- DisableTankControl ();
- m_CameraControl.SetStartPositionAndSize ();
- m_RoundNumber++;
- m_MessageText.text = "ROUND " + m_RoundNumber;
- yield return m_StartWait;
- }
- /// <summary>
- /// 回合开始协程
- /// </summary>
- /// <returns></returns>
- private IEnumerator RoundPlaying ()
- {
- EnableTankControl ();
- m_MessageText.text = string.Empty;
- while (!OneTankLeft())
- {
- yield return null;
- }
- }
- /// <summary>
- /// 游戏结束协程
- /// </summary>
- /// <returns></returns>
- private IEnumerator RoundEnding ()
- {
- DisableTankControl ();
- m_RoundWinner = null;
- m_RoundWinner = GetRoundWinner ();
- if (m_RoundWinner != null)
- m_RoundWinner.m_Wins++;
- m_GameWinner = GetGameWinner ();
- string message = EndMessage ();
- m_MessageText.text = message;
- yield return m_EndWait;
- }
- /// <summary>
- /// 检查激活的坦克数量是否小于等于1,用来设置这局游戏是否结束
- /// </summary>
- /// <returns></returns>
- private bool OneTankLeft()
- {
- ;
- ; i < m_Tanks.Length; i++)
- {
- if (m_Tanks[i].m_Instance.activeSelf)
- numTanksLeft++;
- }
- ;
- }
- /// <summary>
- /// 获取每局的胜者
- /// </summary>
- /// <returns></returns>
- private TankManager GetRoundWinner()
- {
- ; i < m_Tanks.Length; i++)
- {
- if (m_Tanks[i].m_Instance.activeSelf)
- return m_Tanks[i];
- }
- return null;
- }
- /// <summary>
- /// 获取游戏的胜者
- /// </summary>
- /// <returns></returns>
- private TankManager GetGameWinner()
- {
- ; i < m_Tanks.Length; i++)
- {
- if (m_Tanks[i].m_Wins == m_NumRoundsToWin)
- return m_Tanks[i];
- }
- return null;
- }
- /// <summary>
- /// 每回合结束或游戏结束的消息
- /// </summary>
- /// <returns></returns>
- private string EndMessage()
- {
- //默认信息为平局
- string message = "DRAW!";
- //有回合赢家,显示这回合谁赢了
- if(m_RoundWinner != null)
- message = m_RoundWinner.m_ColoredPlayerText + " WINS THE ROUND!";
- message += "\n\n\n\n";
- ; i < m_Tanks.Length; i++)
- {
- message += m_Tanks[i].m_ColoredPlayerText + ": " + m_Tanks[i].m_Wins + " WINS\n";
- }
- if (m_GameWinner != null)
- message = m_GameWinner.m_ColoredPlayerText + " WINS THE GAME!";
- return message;
- }
- /// <summary>
- /// 重置所有坦克
- /// </summary>
- private void ResetAllTanks()
- {
- ; i < m_Tanks.Length; i++)
- {
- m_Tanks[i].Reset();
- }
- }
- /// <summary>
- /// 开启所有坦克的控制
- /// </summary>
- private void EnableTankControl()
- {
- ; i < m_Tanks.Length; i++)
- {
- m_Tanks[i].EnableControl();
- }
- }
- /// <summary>
- /// 关闭所有坦克的控制
- /// </summary>
- private void DisableTankControl()
- {
- ; i < m_Tanks.Length; i++)
- {
- m_Tanks[i].DisableControl();
- }
- }
- }
- }
GameManager
- using System;
- using UnityEngine;
- namespace Complete
- {
- [Serializable]
- public class TankManager
- {
- /// <summary>
- /// 坦克颜色
- /// </summary>
- public Color m_PlayerColor;
- /// <summary>
- /// 坦克孵化点
- /// </summary>
- public Transform m_SpawnPoint;
- /// <summary>
- /// 玩家编号
- /// </summary>
- [HideInInspector] public int m_PlayerNumber;
- /// <summary>
- /// 包含颜色的代表玩家的字符串
- /// </summary>
- [HideInInspector] public string m_ColoredPlayerText;
- /// <summary>
- /// 坦克实例的引用
- /// </summary>
- [HideInInspector] public GameObject m_Instance;
- /// <summary>
- /// 玩家已赢得的局数
- /// </summary>
- [HideInInspector] public int m_Wins;
- /// <summary>
- /// 坦克移动
- /// </summary>
- private TankMovement m_Movement;
- /// <summary>
- /// 坦克射击
- /// </summary>
- private TankShooting m_Shooting;
- /// <summary>
- /// 坦克游戏物体上的canvas
- /// </summary>
- private GameObject m_CanvasGameObject;
- /// <summary>
- /// 设置坦克
- /// </summary>
- public void Setup ()
- {
- m_Movement = m_Instance.GetComponent<TankMovement> ();
- m_Shooting = m_Instance.GetComponent<TankShooting> ();
- m_CanvasGameObject = m_Instance.GetComponentInChildren<Canvas> ().gameObject;
- m_Movement.m_PlayerNumber = m_PlayerNumber;
- m_Shooting.m_PlayerNumber = m_PlayerNumber;
- //设置带颜色的玩家名
- m_ColoredPlayerText = "<color=#" + ColorUtility.ToHtmlStringRGB(m_PlayerColor) + ">PLAYER " + m_PlayerNumber + "</color>";
- //获取并设置坦克及子物体的颜色
- MeshRenderer[] renderers = m_Instance.GetComponentsInChildren<MeshRenderer> ();
- ; i < renderers.Length; i++)
- {
- renderers[i].material.color = m_PlayerColor;
- }
- }
- /// <summary>
- /// 关闭控制
- /// </summary>
- public void DisableControl ()
- {
- m_Movement.enabled = false;
- m_Shooting.enabled = false;
- m_CanvasGameObject.SetActive (false);
- }
- /// <summary>
- /// 开启控制
- /// </summary>
- public void EnableControl ()
- {
- m_Movement.enabled = true;
- m_Shooting.enabled = true;
- m_CanvasGameObject.SetActive (true);
- }
- /// <summary>
- /// 重置坦克状态
- /// </summary>
- public void Reset ()
- {
- m_Instance.transform.position = m_SpawnPoint.position;
- m_Instance.transform.rotation = m_SpawnPoint.rotation;
- m_Instance.SetActive (false);
- m_Instance.SetActive (true);
- }
- }
- }
TankManager
- using UnityEngine;
- using UnityEngine.UI;
- namespace Complete
- {
- /// <summary>
- /// 坦克生命
- /// </summary>
- public class TankHealth : MonoBehaviour
- {
- /// <summary>
- /// 初始坦克生命
- /// </summary>
- public float m_StartingHealth = 100f;
- /// <summary>
- /// 血量滑动条
- /// </summary>
- public Slider m_Slider;
- /// <summary>
- /// 血量滑动条的图片
- /// </summary>
- public Image m_FillImage;
- /// <summary>
- /// 坦克满血的滑动条颜色
- /// </summary>
- public Color m_FullHealthColor = Color.green;
- /// <summary>
- /// 坦克没血的滑动条颜色
- /// </summary>
- public Color m_ZeroHealthColor = Color.red;
- /// <summary>
- /// 坦克爆炸的预设
- /// </summary>
- public GameObject m_ExplosionPrefab;
- /// <summary>
- /// 坦克爆炸的音效
- /// </summary>
- private AudioSource m_ExplosionAudio;
- /// <summary>
- /// 坦克爆炸的粒子系统
- /// </summary>
- private ParticleSystem m_ExplosionParticles;
- /// <summary>
- /// 坦克当前的血量
- /// </summary>
- private float m_CurrentHealth;
- /// <summary>
- /// 坦克是否死亡
- /// </summary>
- private bool m_Dead;
- private void Awake ()
- {
- //实例化爆炸预设并获取爆炸粒子系统的引用
- m_ExplosionParticles = Instantiate (m_ExplosionPrefab).GetComponent<ParticleSystem> ();
- //获取爆炸的音效
- m_ExplosionAudio = m_ExplosionParticles.GetComponent<AudioSource> ();
- //禁用爆炸粒子系统
- m_ExplosionParticles.gameObject.SetActive (false);
- }
- private void OnEnable()
- {
- //设置当前血量为起始血量
- m_CurrentHealth = m_StartingHealth;
- //设置死亡标志位为false
- m_Dead = false;
- //修改血量UI
- SetHealthUI();
- }
- /// <summary>
- /// 坦克受到伤害
- /// </summary>
- /// <param name="amount"></param>
- public void TakeDamage (float amount)
- {
- //修改当前血量
- m_CurrentHealth -= amount;
- //修改血量UI
- SetHealthUI ();
- //如果死亡,当前血量<=0
- if (m_CurrentHealth <= 0f && !m_Dead)
- {
- OnDeath ();
- }
- }
- /// <summary>
- /// 设置坦克血量UI
- /// </summary>
- private void SetHealthUI ()
- {
- //设置滑动条的值为当前血量
- m_Slider.value = m_CurrentHealth;
- //根据当前血量和起始血量的比值设置坦克的滑动条血量的颜色
- m_FillImage.color = Color.Lerp (m_ZeroHealthColor, m_FullHealthColor, m_CurrentHealth / m_StartingHealth);
- }
- /// <summary>
- /// 坦克死亡
- /// </summary>
- private void OnDeath ()
- {
- //设置死亡标志位 true
- m_Dead = true;
- //将爆炸粒子系统的位置移动到坦克的位置
- m_ExplosionParticles.transform.position = transform.position;
- m_ExplosionParticles.gameObject.SetActive (true);
- //播放爆炸粒子系统
- m_ExplosionParticles.Play ();
- //播放爆炸音效
- m_ExplosionAudio.Play();
- //禁用坦克
- gameObject.SetActive (false);
- }
- }
- }
TankHealth
- using UnityEngine;
- namespace Complete
- {
- /// <summary>
- /// 坦克移动
- /// </summary>
- public class TankMovement : MonoBehaviour
- {
- /// <summary>
- /// 玩家编号
- /// </summary>
- ;
- /// <summary>
- /// 坦克的移动速度
- /// </summary>
- public float m_Speed = 12f;
- /// <summary>
- /// 坦克的转向速度
- /// </summary>
- public float m_TurnSpeed = 180f;
- /// <summary>
- /// 移动声源
- /// </summary>
- public AudioSource m_MovementAudio;
- /// <summary>
- /// 空闲时的声音
- /// </summary>
- public AudioClip m_EngineIdling;
- /// <summary>
- /// 移动时的声音
- /// </summary>
- public AudioClip m_EngineDriving;
- /// <summary>
- /// 音高范围
- /// </summary>
- public float m_PitchRange = 0.2f;
- /// <summary>
- /// 控制前后移动的轴名
- /// </summary>
- private string m_MovementAxisName;
- /// <summary>
- /// 控制
- /// </summary>
- private string m_TurnAxisName;
- /// <summary>
- /// 刚体
- /// </summary>
- private Rigidbody m_Rigidbody;
- /// <summary>
- /// 移动输入
- /// </summary>
- private float m_MovementInputValue;
- /// <summary>
- /// 转向输入
- /// </summary>
- private float m_TurnInputValue;
- /// <summary>
- /// 原始音高
- /// </summary>
- private float m_OriginalPitch;
- private void Awake ()
- {
- m_Rigidbody = GetComponent<Rigidbody> ();
- }
- private void OnEnable ()
- {
- m_Rigidbody.isKinematic = false;
- m_MovementInputValue = 0f;
- m_TurnInputValue = 0f;
- }
- private void OnDisable ()
- {
- m_Rigidbody.isKinematic = true;
- }
- private void Start ()
- {
- //通过玩家编号获取输入轴
- m_MovementAxisName = "Vertical" + m_PlayerNumber;
- m_TurnAxisName = "Horizontal" + m_PlayerNumber;
- //存储原始音高
- m_OriginalPitch = m_MovementAudio.pitch;
- }
- private void Update ()
- {
- //获取输入轴的值
- m_MovementInputValue = Input.GetAxis (m_MovementAxisName);
- m_TurnInputValue = Input.GetAxis (m_TurnAxisName);
- EngineAudio ();
- }
- /// <summary>
- /// 处理引擎的声音
- /// </summary>
- private void EngineAudio ()
- {
- //如果没有输入
- if (Mathf.Abs (m_MovementInputValue) < 0.1f && Mathf.Abs (m_TurnInputValue) < 0.1f)
- {
- //如果正在播放移动的声音
- if (m_MovementAudio.clip == m_EngineDriving)
- {
- //播放闲置的声音
- m_MovementAudio.clip = m_EngineIdling;
- m_MovementAudio.pitch = Random.Range (m_OriginalPitch - m_PitchRange, m_OriginalPitch + m_PitchRange);
- m_MovementAudio.Play ();
- }
- }
- //如果有输入
- else
- {
- //如果正在播放闲置的声音
- if (m_MovementAudio.clip == m_EngineIdling)
- {
- //播放移动的声音
- m_MovementAudio.clip = m_EngineDriving;
- m_MovementAudio.pitch = Random.Range(m_OriginalPitch - m_PitchRange, m_OriginalPitch + m_PitchRange);
- m_MovementAudio.Play();
- }
- }
- }
- private void FixedUpdate ()
- {
- //移动
- Move ();
- //旋转
- Turn ();
- }
- /// <summary>
- /// 移动
- /// </summary>
- private void Move ()
- {
- //创建一个坦克的速度向量
- Vector3 movement = transform.forward * m_MovementInputValue * m_Speed * Time.deltaTime;
- //刚体移动
- m_Rigidbody.MovePosition(m_Rigidbody.position + movement);
- }
- /// <summary>
- /// 旋转
- /// </summary>
- private void Turn ()
- {
- //根据输入,旋转速度以及每帧的时间计算旋转的值
- float turn = m_TurnInputValue * m_TurnSpeed * Time.deltaTime;
- //创建y轴的四元数旋转
- Quaternion turnRotation = Quaternion.Euler (0f, turn, 0f);
- //刚体旋转
- m_Rigidbody.MoveRotation (m_Rigidbody.rotation * turnRotation);
- }
- }
- }
TankMovement
- using UnityEngine;
- using UnityEngine.UI;
- namespace Complete
- {
- /// <summary>
- /// 坦克射击
- /// </summary>
- public class TankShooting : MonoBehaviour
- {
- /// <summary>
- /// 玩家编号
- /// </summary>
- ;
- /// <summary>
- /// 炮弹刚体
- /// </summary>
- public Rigidbody m_Shell;
- /// <summary>
- /// 射击的位置
- /// </summary>
- public Transform m_FireTransform;
- /// <summary>
- /// 射击的箭头滑动条
- /// </summary>
- public Slider m_AimSlider;
- /// <summary>
- /// 发射声音
- /// </summary>
- public AudioSource m_ShootingAudio;
- /// <summary>
- /// 充能声音
- /// </summary>
- public AudioClip m_ChargingClip;
- /// <summary>
- /// 开火声音
- /// </summary>
- public AudioClip m_FireClip;
- /// <summary>
- /// 发射炮弹最小的力
- /// </summary>
- public float m_MinLaunchForce = 15f;
- /// <summary>
- /// 发射炮弹最大的力
- /// </summary>
- public float m_MaxLaunchForce = 30f;
- /// <summary>
- /// 发射炮弹的最大充能时间
- /// </summary>
- public float m_MaxChargeTime = 0.75f;
- /// <summary>
- /// 控制发射的轴名
- /// </summary>
- private string m_FireButton;
- /// <summary>
- /// 当前的发射力
- /// </summary>
- private float m_CurrentLaunchForce;
- /// <summary>
- /// 充能速度
- /// </summary>
- private float m_ChargeSpeed;
- /// <summary>
- /// 是否已发射
- /// </summary>
- private bool m_Fired;
- private void OnEnable()
- {
- //重置当前发射力和箭头滑动条的值
- m_CurrentLaunchForce = m_MinLaunchForce;
- m_AimSlider.value = m_MinLaunchForce;
- }
- private void Start ()
- {
- //根据玩家编号设置 发射的轴名
- m_FireButton = "Fire" + m_PlayerNumber;
- //计算发射充能
- m_ChargeSpeed = (m_MaxLaunchForce - m_MinLaunchForce) / m_MaxChargeTime;
- }
- private void Update ()
- {
- //设置箭头滑动条的值
- m_AimSlider.value = m_MinLaunchForce;
- //如果当前的发射力大于最大发射力,并且没有发射
- if (m_CurrentLaunchForce >= m_MaxLaunchForce && !m_Fired)
- {
- //用最大发射力发射
- m_CurrentLaunchForce = m_MaxLaunchForce;
- Fire ();
- }
- //如果按下了发射按钮
- else if (Input.GetButtonDown (m_FireButton))
- {
- //设置发射标志位为false
- m_Fired = false;
- //设置当前发射力为最小力
- m_CurrentLaunchForce = m_MinLaunchForce;
- //播放充能声音
- m_ShootingAudio.clip = m_ChargingClip;
- m_ShootingAudio.Play ();
- }
- //如果发射按钮被按住且炮弹并没有发射
- else if (Input.GetButton (m_FireButton) && !m_Fired)
- {
- //更新当前发射力
- m_CurrentLaunchForce += m_ChargeSpeed * Time.deltaTime;
- //更新箭头滑动条的值
- m_AimSlider.value = m_CurrentLaunchForce;
- }
- //如果发射键松开且炮弹没有发射
- else if (Input.GetButtonUp (m_FireButton) && !m_Fired)
- {
- //发射炮弹
- Fire ();
- }
- }
- /// <summary>
- /// 发射
- /// </summary>
- private void Fire ()
- {
- //设置发射标志位
- m_Fired = true;
- //获取炮弹刚体的引用
- Rigidbody shellInstance =
- Instantiate (m_Shell, m_FireTransform.position, m_FireTransform.rotation) as Rigidbody;
- //设置刚体的速度
- shellInstance.velocity = m_CurrentLaunchForce * m_FireTransform.forward;
- //播放发射声音
- m_ShootingAudio.clip = m_FireClip;
- m_ShootingAudio.Play ();
- //重置当前发射力为最小发射力
- m_CurrentLaunchForce = m_MinLaunchForce;
- }
- }
- }
TankShooting
- using UnityEngine;
- namespace Complete
- {
- /// <summary>
- /// 炮弹爆炸
- /// </summary>
- public class ShellExplosion : MonoBehaviour
- {
- /// <summary>
- /// 坦克层
- /// </summary>
- public LayerMask m_TankMask;
- public ParticleSystem m_ExplosionParticles;
- /// <summary>
- /// 爆炸声源
- /// </summary>
- public AudioSource m_ExplosionAudio;
- /// <summary>
- /// 最大伤害
- /// </summary>
- public float m_MaxDamage = 100f;
- /// <summary>
- /// 爆炸力
- /// </summary>
- public float m_ExplosionForce = 1000f;
- /// <summary>
- /// 炮弹的生命周期
- /// </summary>
- public float m_MaxLifeTime = 2f;
- /// <summary>
- /// 爆炸半径
- /// </summary>
- public float m_ExplosionRadius = 5f;
- private void Start ()
- {
- //如果炸弹没有被销毁,经过指定时间后自动销毁
- Destroy (gameObject, m_MaxLifeTime);
- }
- private void OnTriggerEnter (Collider other)
- {
- //以炮弹为中心,爆炸半径为半径发射相交球
- Collider[] colliders = Physics.OverlapSphere (transform.position, m_ExplosionRadius, m_TankMask);
- //循环遍历碰撞体
- ; i < colliders.Length; i++)
- {
- //获取目标刚体
- Rigidbody targetRigidbody = colliders[i].GetComponent<Rigidbody> ();
- //如果没有刚体,则继续检测下一个
- if (!targetRigidbody)
- continue;
- //目标刚体添加爆炸力
- targetRigidbody.AddExplosionForce (m_ExplosionForce, transform.position, m_ExplosionRadius);
- //获取目标的血量
- TankHealth targetHealth = targetRigidbody.GetComponent<TankHealth> ();
- //如果没有,检测下一个
- if (!targetHealth)
- continue;
- //根据目标位置计算伤害
- float damage = CalculateDamage (targetRigidbody.position);
- //目标受到伤害
- targetHealth.TakeDamage (damage);
- }
- m_ExplosionParticles.transform.parent = null;
- //播放爆炸粒子效果
- m_ExplosionParticles.Play();
- //播放爆炸声音
- m_ExplosionAudio.Play();
- //定时销毁粒子系统
- Destroy (m_ExplosionParticles.gameObject, m_ExplosionParticles.duration);
- //销毁炮弹
- Destroy (gameObject);
- }
- /// <summary>
- /// 计算伤害
- /// </summary>
- /// <param name="targetPosition">目标位置</param>
- /// <returns></returns>
- private float CalculateDamage (Vector3 targetPosition)
- {
- //创建一个从自身到目标的向量
- Vector3 explosionToTarget = targetPosition - transform.position;
- //计算这个向量的模
- float explosionDistance = explosionToTarget.magnitude;
- //计算相对距离
- float relativeDistance = (m_ExplosionRadius - explosionDistance) / m_ExplosionRadius;
- //根据距离比例和最大伤害计算伤害
- float damage = relativeDistance * m_MaxDamage;
- //确保最小伤害为0
- damage = Mathf.Max (0f, damage);
- return damage;
- }
- }
- }
ShellExplosion
- using UnityEngine;
- namespace Complete
- {
- /// <summary>
- /// UI朝向控制
- /// </summary>
- public class UIDirectionControl : MonoBehaviour
- {
- /// <summary>
- /// 是否使用相对旋转
- /// </summary>
- public bool m_UseRelativeRotation = true;
- /// <summary>
- /// 局部旋转
- /// </summary>
- private Quaternion m_RelativeRotation;
- private void Start ()
- {
- //局部旋转为父对象的局部旋转
- m_RelativeRotation = transform.parent.localRotation;
- }
- private void Update ()
- {
- if (m_UseRelativeRotation)
- transform.rotation = m_RelativeRotation;
- }
- }
- }
UIDirectionControl
视频:https://pan.baidu.com/s/1eRFbQYA
项目:https://pan.baidu.com/s/1midmmuc
Tanks!Tutorial 学习的更多相关文章
- Python Tutorial 学习(八)--Errors and Exceptions
Python Tutorial 学习(八)--Errors and Exceptions恢复 Errors and Exceptions 错误与异常 此前,我们还没有开始着眼于错误信息.不过如果你是一 ...
- Django 1.7 Tutorial 学习笔记
官方教程在这里 : Here 写在前面的废话:)) 以前学习新东西,第一想到的是找本入门教程,按照书上做一遍.现在看了各种网上的入门教程后,我觉得还是看官方Tutorial靠谱.书的弊端一说一大推 本 ...
- 深度学习 Deep Learning UFLDL 最新 Tutorial 学习笔记 1:Linear Regression
1 前言 Andrew Ng的UFLDL在2014年9月底更新了. 对于開始研究Deep Learning的童鞋们来说这真的是极大的好消息! 新的Tutorial相比旧的Tutorial添加了Conv ...
- SQL Expression Language Tutorial 学习笔记一
http://docs.sqlalchemy.org/en/latest/core/tutorial.html Google 翻译了一下 SQLAlchemy Expression Language, ...
- FFmpeg的tutorial 学习
一.前言: 这是一个学习 FFmpeg 的 tutorial 系列. 这个是一个对初学者比较友好的FFmpeg学习教程,作者一步步引导我们实现了一个音视频同步的播放器. 参考链接: 原文地址: htt ...
- Python Tutorial 学习(六)--Modules
6. Modules 当你退出Python的shell模式然后又重新进入的时候,之前定义的变量,函数等都会没有了. 因此, 推荐的做法是将这些东西写入文件,并在适当的时候调用获取他们. 这就是为人所知 ...
- Python Tutorial 学习(四)--More Control Flow Tools
4.1 if 表达式 作为最为人熟知的if.你肯定对这样的一些表达式不感到陌生: >>> x = int(raw_input("Please enter an intege ...
- Python Tutorial 学习(一)--Whetting Your Appetite
Whetting Your Appetite [吊你的胃口]... 这里就直接原文奉上了... If you do much work on computers, eventually you fin ...
- 深度学习 Deep Learning UFLDL 最新Tutorial 学习笔记 5:Softmax Regression
Softmax Regression Tutorial地址:http://ufldl.stanford.edu/tutorial/supervised/SoftmaxRegression/ 从本节開始 ...
随机推荐
- Ubuntu 修改 /etc/resolv.conf 被清空 或重启不生效解决
sudo gedit /etc/NetworkManager/NetworkManager.conf 注释掉 dns=dnsmasq [main] plugins=ifupdown,keyfile,o ...
- Capjoint的merrcmd生成二次曲线的misfit原理
http://www.personal.psu.edu/jhm/f90/lectures/lsq2.html
- 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 ...
- python random模块(获取随机数)
如果要使用random模块,需要先导入 import random 1.random.random() #用于生成一个0到1的随机浮点数 2.random.uniform(a,b) #用于生成一个 ...
- 玩转 React 【第03期】:邂逅 React 组件
上期回顾 前文我们讲解了 React 模板 JSX,接着我们继续来看看 React 组件又是如何工作的呢? 组件化开发到了今天已经是大家的共识,在 React 中,组件同样也是组成我们整个项目的基本单 ...
- 关于 数据库 my_slq的 安装及其卸载
安装的时候 注意事项 自定后 根据电脑的系统版本 选择32 或者64 然后选择→方向键 密码默认是123456 或者 123123 查看装的数据库是否安装好了 如何完全卸载 mysql 数据库 ...
- day 30 客户端获取cmd 命令的步骤
import subprocessimport structimport jsonfrom socket import *server=socket(AF_INET,SOCK_STREAM)serve ...
- vue 手写组件 集合
Num.1 : 链接 向右滑动, 显示删除按钮, 根据touchStart touchEnd 的 clientX 差距 > 30; 说明是向左滑动, 显示; 改变 e.currentTarg ...
- kbmMWLog同时输出日志到多个日志管理器
kbmMWLog日志框架,针对不同的业务情况,提供了多种日志管理器: TkbmMWStreamLogManager TkbmMWLocalFileLogManager TkbmMWSystemLogM ...
- python 26个技巧
26个你不知道的Python技巧 Python是目前世界上最流行的编程语言之一.因为: 1.它容易学习 2.它用途超广 3.它有非常多的开源支持(大量的模块和库) 不好意思,优达菌又啰嗦了. 本文 ...