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/ 从本节開始 ...
随机推荐
- 单元测试UI
cnpm install -g --save mocha cnpm install -g --save chai cnpm install -g --save istanbul const {sho ...
- 2.8 C++参数初始化表
参考:http://www.weixueyuan.net/view/6340.html 总结: 参数初始化表可以为任何数据成员进行初始化. 初始化const成员变量的唯一方法只有利用参数初始化表. 通 ...
- 使用DevExpress Reports和PDF Viewer创建AcroForm Designer
众所周知,交互式表单(AcroForms)是PDF标准的重要组成部分,AcroForms允许开发者和开发者的用户创建可填写的PDF文档.尽管WinForms和WPF PDF Viewers不支持交互式 ...
- 数字签名-MD5
MD5是信息摘要的意思,报文产生摘要是唯一的(1:1),而且是单向的(通过摘要反推不出源报文) java中的java.security.MessageDigest类,参考MessageDigest的功 ...
- tensorflow-LSTM-网络输出与多隐层节点
本文从tensorflow的代码层面理解LSTM. 看本文之前,需要先看我的这两篇博客 https://www.cnblogs.com/yanshw/p/10495745.html 谈到网络结构 ht ...
- Java 内存监控命令简介(零)
一.Java性能监控与调优命令.工具简介 1.jps :查看当前运行的Java程序端口号,包括运行jps的程序端口号. 2.jinfo :查看Java进程的运行时信息. 3.jmap + MAT :通 ...
- php优秀框架codeigniter学习系列——CI_URI类学习
这篇文章主要介绍CI核心框架工具类CI_URI. 该类主要用来解析uri和决定路由的.关于URI和URL的关系请参考这位朋友的文章.简单来说URI是唯一定位的资源,URL是唯一资源的一个网络可能访问路 ...
- JAVA自动补全代码
打开eclipse(对myeclipse同样适用) 找到窗口(windows)菜单,打开最后一项首选项(Preferences)找到下属菜单java打开,打开里边的编辑器(Editor)菜单,点击内容 ...
- 运行和管理Rabbit
节点描述的是一个Erlang节点运行着一个Erlang应用程序.Erlang虚拟机的每个实例我们称之为节点.多个Erlang应用程序可以运行在同一个节点之上.节点之间可以进行本地通信.在RabbitM ...
- SQL注入之Sqli-labs系列第十八关(基于错误的用户代理,头部POST注入)
开始挑战第十八关(Header Injection - Uagent field - Error based) 常见的HTTP注入点产生位置为[Referer].[X-Forwarded-For].[ ...