视频笔记-Uniy官方教程Tanks-子弹及发射子弹-P5~P6

Unity 官方教学链接
B站双语机翻链接

5 子弹

为 Shell 模型添加胶囊碰撞体和刚体组件,调整碰撞体大小
视频笔记-Uniy官方教程Tanks-子弹及发射子弹-P5~P6_第1张图片
视频笔记-Uniy官方教程Tanks-子弹及发射子弹-P5~P6_第2张图片

为 Shell 添加子物体 ShellExplosion 预制体,并为预制体添加音效组件
视频笔记-Uniy官方教程Tanks-子弹及发射子弹-P5~P6_第3张图片
视频笔记-Uniy官方教程Tanks-子弹及发射子弹-P5~P6_第4张图片
为 Shell 添加脚本 ShellExplosion.cs,代码如下:

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);
        }
		// 解除父子关系是为了保证 Shell 被删除后,粒子系统依然能继续运行
        m_ExplosionParticles.transform.parent = null;

        m_ExplosionParticles.Play();

        m_ExplosionAudio.Play();

        Destroy(m_ExplosionParticles.gameObject, m_ExplosionParticles.main.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;

        damage = Mathf.Max(0f, damage);

        return damage;
    }
}

将 Shell 添加为预制体,将其删除,保存场景。

6 发射子弹

在 Tank 的炮管位置添加一个空物体
视频笔记-Uniy官方教程Tanks-子弹及发射子弹-P5~P6_第5张图片
在 Tank 原有的 Canvas 下添加 Slider,并做下列调整:
视频笔记-Uniy官方教程Tanks-子弹及发射子弹-P5~P6_第6张图片
继续调整 Slider:
视频笔记-Uniy官方教程Tanks-子弹及发射子弹-P5~P6_第7张图片
视频笔记-Uniy官方教程Tanks-子弹及发射子弹-P5~P6_第8张图片
视频笔记-Uniy官方教程Tanks-子弹及发射子弹-P5~P6_第9张图片
为 Tank 添加脚本 TankShooting.cs,代码如下:

using UnityEngine;
using UnityEngine.UI;

public class TankShooting : MonoBehaviour
{
    public int m_PlayerNumber = 1;       
    public Rigidbody m_Shell;            
    public Transform m_FireTransform;    
    public Slider m_AimSlider;           
    public AudioSource m_ShootingAudio;  
    public AudioClip m_ChargingClip;     
    public AudioClip m_FireClip;         
    public float m_MinLaunchForce = 15f; 
    public float m_MaxLaunchForce = 30f; 
    public float m_MaxChargeTime = 0.75f;

    
    private string m_FireButton;         
    private float m_CurrentLaunchForce;  
    private float m_ChargeSpeed;         
    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()
    {
        // Track the current state of the fire button and make decisions based on the current launch force.
        m_AimSlider.value = m_MinLaunchForce;

        if (m_CurrentLaunchForce >= m_MaxLaunchForce && !m_Fired)
        {
            // at max charge, not yet fired
            m_CurrentLaunchForce = m_MaxLaunchForce;
            Fire();
        }
        else if (Input.GetButtonDown(m_FireButton))
        {
            // have we pressed fire for the first time?
            m_Fired = false;
            m_CurrentLaunchForce = m_MinLaunchForce;
            m_ShootingAudio.clip = m_ChargingClip;
            m_ShootingAudio.Play();
        }
        else if (Input.GetButton(m_FireButton) && !m_Fired)
        {
            // Holding the fire button, not yet fired
            m_CurrentLaunchForce += m_ChargeSpeed * Time.deltaTime;
            m_AimSlider.value = m_CurrentLaunchForce;
        }
        else if (Input.GetButtonUp(m_FireButton) && !m_Fired)
        {
            // we released the button, having not fired yet
            Fire();
        }
    }


    private void Fire()
    {
        // Instantiate and launch the shell.
        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;
    }
}

在编辑器中为该脚本的公共变量赋上合适的物体:
视频笔记-Uniy官方教程Tanks-子弹及发射子弹-P5~P6_第10张图片
将 Tank 更新为预制体之后将其删除(删除前可以测试一下,默认开火键是空格)。

你可能感兴趣的:(Unity,学习笔记)