該源代碼轉載自Unity遊戲案例中的TANKS代碼中
------------來自第二次使用Unity3D製作遊戲的遊戲製作新人小白
一、代碼自我解析
二、油管學習地址
三、Unity3D源代碼
一、源代碼自我解析
using UnityEngine;
public class ShellExplosion : MonoBehaviour
{
public LayerMask m_TankMask; // 加載玩家
public ParticleSystem m_ExplosionParticles; // 加載粒子效果(炮彈爆炸)
public AudioSource m_ExplosionAudio; // 加載爆炸音效
public float m_MaxDamage = 100f; // 設置最大傷害數值
public float m_ExplosionForce = 1000f; // 加載爆炸中心的坦克的力
public float m_MaxLifeTime = 2f; // 移除炮彈前的時間,以秒爲單位
public float m_ExplosionRadius = 5f; // 爆炸半徑
private void Start()
{
// 如果到那時它還沒有被銷燬,那就在它的生命週期結束後銷燬它。
Destroy(gameObject, m_MaxLifeTime);
}
private void OnTriggerEnter(Collider other)
{
// Find all the tanks in an area around the shell and damage them.
Collider[] colliders = Physics.OverlapSphere(transform.position, m_ExplosionRadius, m_TankMask);
// 遍歷所有碰撞器
for (int i = 0; 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();
// 一旦粒子完成,摧毀他們的遊戲對象
ParticleSystem.MainModule mainModule = m_ExplosionParticles.main;
Destroy(m_ExplosionParticles.gameObject, mainModule.duration);
Destroy(gameObject);
}
private float CalculateDamage(Vector3 targetPosition)
{
// Calculate the amount of damage a target should take based on it's position.
// 創建一個從炮彈到目標的向量
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;
}
}
// 以上只是自己對於該代碼的理解,如有誤還望指出讓我及時改正。
二、油管學習Unity地址
https://www.youtube.com/watch?v=paLLfWd2k5A
三、Unity3D中該案例源代碼:
using UnityEngine;
namespace Complete
{
public class ShellExplosion : MonoBehaviour
{
public LayerMask m_TankMask; // Used to filter what the explosion affects, this should be set to "Players".
public ParticleSystem m_ExplosionParticles; // Reference to the particles that will play on explosion.
public AudioSource m_ExplosionAudio; // Reference to the audio that will play on explosion.
public float m_MaxDamage = 100f; // The amount of damage done if the explosion is centred on a tank.
public float m_ExplosionForce = 1000f; // The amount of force added to a tank at the centre of the explosion.
public float m_MaxLifeTime = 2f; // The time in seconds before the shell is removed.
public float m_ExplosionRadius = 5f; // The maximum distance away from the explosion tanks can be and are still affected.
private void Start ()
{
// If it isn't destroyed by then, destroy the shell after it's lifetime.
Destroy (gameObject, m_MaxLifeTime);
}
private void OnTriggerEnter (Collider other)
{
// Collect all the colliders in a sphere from the shell's current position to a radius of the explosion radius.
Collider[] colliders = Physics.OverlapSphere (transform.position, m_ExplosionRadius, m_TankMask);
// Go through all the colliders...
for (int i = 0; i < colliders.Length; i++)
{
// ... and find their rigidbody.
Rigidbody targetRigidbody = colliders[i].GetComponent<Rigidbody> ();
// If they don't have a rigidbody, go on to the next collider.
if (!targetRigidbody)
continue;
// Add an explosion force.
targetRigidbody.AddExplosionForce (m_ExplosionForce, transform.position, m_ExplosionRadius);
// Find the TankHealth script associated with the rigidbody.
TankHealth targetHealth = targetRigidbody.GetComponent<TankHealth> ();
// If there is no TankHealth script attached to the gameobject, go on to the next collider.
if (!targetHealth)
continue;
// Calculate the amount of damage the target should take based on it's distance from the shell.
float damage = CalculateDamage (targetRigidbody.position);
// Deal this damage to the tank.
targetHealth.TakeDamage (damage);
}
// Unparent the particles from the shell.
m_ExplosionParticles.transform.parent = null;
// Play the particle system.
m_ExplosionParticles.Play();
// Play the explosion sound effect.
m_ExplosionAudio.Play();
// Once the particles have finished, destroy the gameobject they are on.
ParticleSystem.MainModule mainModule = m_ExplosionParticles.main;
Destroy (m_ExplosionParticles.gameObject, mainModule.duration);
// Destroy the shell.
Destroy (gameObject);
}
private float CalculateDamage (Vector3 targetPosition)
{
// Create a vector from the shell to the target.
Vector3 explosionToTarget = targetPosition - transform.position;
// Calculate the distance from the shell to the target.
float explosionDistance = explosionToTarget.magnitude;
// Calculate the proportion of the maximum distance (the explosionRadius) the target is away.
float relativeDistance = (m_ExplosionRadius - explosionDistance) / m_ExplosionRadius;
// Calculate damage as this proportion of the maximum possible damage.
float damage = relativeDistance * m_MaxDamage;
// Make sure that the minimum damage is always 0.
damage = Mathf.Max (0f, damage);
return damage;
}
}
}