07 赶紧建炮塔(和儿子一起编游戏-塔防系列 )

7.1 基本概念

炮塔炮塔,顾名思义首先脑袋要会转,其次是要冲着坏蛋转,这是基本要求。此外炮塔还要有一定的美感,毕竟是在玩游戏。

7.2 做一个炮塔的样子其实不容易

美工这一块确实是老余的短板,流行的3D软件都不会玩。不过世上无难事,我们有某宝。功夫不负有心人,老余发现某宝上面U3D的素材还是挺多的,当下决定买了一款自己觉得还不错的,没曾想,等老余右键菜单选择Import Package导入后,让休息好了的小余看见了,居然给老余第一个想用的,威力最小的一款起了一个外号,叫马桶炮塔,好吧马桶炮塔看起来确实像马桶,谁让老余舍不得掏银子呢

老余把马桶炮塔码好位置,给马桶炮塔起了个名字StdTurret,给可以转动的部分起了个名字Head。

接下来,他要做一件必要的事情,就是给敌人做一个标签,所有带上这个标签的物件,不管长成啥样,都被视为敌人

把自定义的Tag放到Enemy的Prefab里面去,这样就不会有漏网得了:

7.3 发现敌人

现在老余需要给炮塔绑定一段炮塔专有C#脚本:Turret (Script)

发现敌人的要点就是:

  1. 给敌人冠以Tag标签,这样就全都在炮塔的监视范围内了
  2. 筛选出在射程范围内的离的最近的那个小蛋

怎么看射程范围呢,U3D给了一个小Tip,在脚本里面写这么一段:

    /// <summary>
    /// 重载设计图中的旋转圈,可以用这个功能看到射界
    /// </summary>
    private void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position,range);
    }

等回到设计界面,看到的就是这个样子,讲真的,老余还挺需要这个功能,不然不是射程太近,就是射程超远,自己都看不见,啥时候不想看了,再注释掉这段代码就行:

筛选离的最近的敌人是UpdateTarget

using UnityEngine;

public class Turret : MonoBehaviour
{
    public Transform target;
    public float range = 15f;

    public string enemyTag = "Enemy";

    // Start is called before the first frame update
    void Start()
    {
        InvokeRepeating("UpdateTarget", 0f, 0.5f);  // 每间隔0.5秒,调用一下UpdateTarget,让炮塔保持指向敌人
    }

    void UpdateTarget()
    {
        // 找出游戏里面出来的所有敌人
        GameObject[] enemies = GameObject.FindGameObjectsWithTag(enemyTag);
        float shortestDistance = Mathf.Infinity; 
        GameObject nearestEnemy = null; // 记录最近距离的敌人信息,初始为空

        foreach (GameObject enemy in enemies)
        {
            float distanceToEnemy = Vector3.Distance(transform.position, enemy.transform.position);
            if (distanceToEnemy < shortestDistance)
            {
                shortestDistance = distanceToEnemy;
                nearestEnemy = enemy;
            }
            // 找到最近的敌人,而且在射程内,则实体化target
            if (nearestEnemy != null && shortestDistance <= range)
            {
                target = nearestEnemy.transform;
            }
            else
            {
                target = null;
            }
        }

    }

    // Update is called once per frame
    void Update()
    {
        if (target == null)
        {
            return;
        }
    }

    /// <summary>
    /// 重载设计图中的旋转圈,可以用这个功能看到射界
    /// </summary>
    private void OnDrawGizmosSelected()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position,range);
    }
}

7.4 瞄准敌人

下一步就是让这个炮塔转脑袋了,当然这个脑袋要冲着坏蛋转,在Turret那个C#中增加下面的内容,关键点就是LockOnTarget,Shoot只是一个空函数,预留给炮弹用的:

public Transform partToRotate;  // 旋转部分的引用
public float turnSpeed = 10f;  // 炮塔转动速度

void Update()
    {
        if (target == null)
        {
            return;
        }

        LockOnTarget();
        if (fireCountdown <= 0)
        {

            Shoot();
            fireCountdown = 1 / fireRate;  // 连续发射及考量频率
        }

        fireCountdown -= Time.deltaTime;
    }

    /// <summary>
    /// 锁定敌人
    /// </summary>
    void LockOnTarget()
    {
        // Target lock on
        Vector3 dir = target.position - transform.position;  // 炮塔和敌人的间距向量
        Quaternion lookRotation = Quaternion.LookRotation(dir);
        // 使用Lerp转动更加柔和,简单写的话可以Vector3 rotation = lookRotation.eulerAngles, 不过这个转动就有点硬
        Vector3 rotation = Quaternion.Lerp(partToRotate.rotation, lookRotation, Time.deltaTime * turnSpeed).eulerAngles;
        partToRotate.rotation = Quaternion.Euler(0f, rotation.y, 0f);
}

记住把Head拉到PartToRotate这边来:

从效果图上面看,我们的小马桶炮塔一直在摆着脑袋指向敌人,上图有真相:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值