首页 > 其他分享 >Unity-波数-杀怪-学习

Unity-波数-杀怪-学习

时间:2024-11-26 13:33:07浏览次数:7  
标签:Vector3 杀怪 void float private Unity 波数 using public

学习目标:


学习内容:

  1. 场景的摆放以及自动门的脚本已经发过--“Unity自动门笔记”,可以前往观看摆放

  2. 这里主要注意的是AI的NavMesh 使用

  3. 接下来是角色的移动以及发射子弹,需要准备子弹的预支体以及简单的枪管

    using UnityEngine;
    
    [RequireComponent(typeof(Rigidbody))]
    public class PlayerMovement : LivingEntity
    {
        private Rigidbody rb;
        private Vector3 moveInput;
        [SerializeField] private float moveSpeed;
    
        //private void Start()
        //{
        //    rb = GetComponent<Rigidbody>();
        //}
        protected override void Start()
        {
            base.Start();
            rb = GetComponent<Rigidbody>();
        }
    
        private void Update()
        {
            moveInput = new Vector3(Input.GetAxis("Horizontal"), 0f, Input.GetAxis("Vertical"));
            LookAtCursor();
        }
    
        private void FixedUpdate()
        {
            rb.MovePosition(rb.position + moveInput * moveSpeed * Time.fixedDeltaTime);
        }
    
        private void LookAtCursor()
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            Plane plane = new Plane(Vector3.up, Vector3.zero);
    
            float distToGround;
            if (plane.Raycast(ray, out distToGround))
            {
                Vector3 point = ray.GetPoint(distToGround);
                Vector3 rightPoint = new Vector3(point.x, transform.position.y, point.z);
    
                transform.LookAt(rightPoint);
            }
        }
    }
    

    放置在预制体的子弹脚本:

    
    using UnityEngine;
    
    public class GunController : MonoBehaviour
    {
        public Transform firePoint;
        public GameObject projectilePrefab;
        [SerializeField] private float fireRate = 0.5f;
        private float timer;
    
        private void Update()
        {
            if (Input.GetMouseButton(0))
            {
                shot();
            }
        }
        public void shot()
        {
            timer += Time.deltaTime;
            if (timer > fireRate)
            {
                timer = 0;
                GameObject spawnProjectile = Instantiate(projectilePrefab, firePoint.position, firePoint.rotation);
            }
        }
    
    }
    

4.接下来是敌人的生成以及追击角色

using UnityEngine.UI;
using UnityEngine;
using UnityEngine.UIElements;

public class Spawner : MonoBehaviour
{
    public GameObject enemyPrefab;
    public Wave[] waves;
    [Header("JUST FOR CHECK")]
    [SerializeField] private Wave currentWave;//当前的波数
    [SerializeField] private int currentIndex;//当前波数索引
    public int spawnAliveNum;//存活的个数
    public float nextSpawnTime;//下一波怪的生成时间
    public int waitSpawnNum;//等待怪物的生成时间
    [SerializeField]private Text spawnSum;//波数总和
    private int enemySum;//怪物总量
    private int spawnCount;//记录总波数
    [SerializeField]private Text Score;//分数
    private int temp;//记录杀敌数
    public Text gameOver;//记录怪物的个数,无就游戏结束
    private void Start()
    {
        NextWave();
        for (int i = 0; i < waves.Length; i++)
        {
            currentWave = waves[i];
            enemySum += currentWave.enemyNum;
            spawnCount++;
        }
        Debug.Log("<color=green>怪物总数  </color>" + enemySum);
        spawnSum.text = "总波数:" + spawnCount;
    }

    private void NextWave()
    {
        currentIndex++; 
        Debug.Log(string.Format("Current Wave :{0}", currentIndex));
        if (currentIndex - 1 < waves.Length)
        {
            currentWave = waves[currentIndex - 1];
            waitSpawnNum = currentWave.enemyNum;//记录等待生成的敌人
            spawnAliveNum = currentWave.enemyNum;//记录存活的敌人
        }


    }
    private void Update()
    {
        if (waitSpawnNum > 0 && Time.time > nextSpawnTime)
        {
            waitSpawnNum--;
            GameObject spawnEnemy = Instantiate(enemyPrefab, transform.position, Quaternion.identity);//生成怪物
            spawnEnemy.GetComponent<Enemy>().onDeath += EnemyDeath;//订阅事件
            nextSpawnTime = Time.time + currentWave.timeBtwSpawn;
        }
        GameEnd();
        Score.text = "杀敌数:" + temp;
    }
    private void EnemyDeath()
    {
        spawnAliveNum--;
        if (spawnAliveNum <= 0)
        {
            NextWave();
        }
        temp++;
        enemySum--; //总敌人数减少,直到为0游戏结束
        Debug.Log("<color=yellow> enemySum </color>" + enemySum);
    }
    public void GameEnd()
    {
        if (enemySum <= 0)
        {
            gameOver.gameObject.SetActive(true);
        }
    }

}

 

using UnityEngine.AI;
using UnityEngine;
using System.Collections;
using UnityEditor.Search;
using System;

[RequireComponent(typeof(NavMeshAgent))]
public class Enemy : LivingEntity
{
    private NavMeshAgent navMeshAgent;
    private Transform target;
    [SerializeField] private float updateRate;
    [SerializeField] private float scaleDownDuration = 0.6f; // 缩小到消失的持续时间
    protected override void Start()
    {
        base.Start();
        navMeshAgent = GetComponent<NavMeshAgent>();
        if (navMeshAgent != null)
        {
            target = GameObject.FindWithTag("Player").GetComponent<Transform>();
        }
        onDeath += PlayDeathParticle;
        StartCoroutine(UpdatePath());
    }

    private void PlayDeathParticle()
    {
        ParticleSystem particleSystem = GetComponent<ParticleSystem>();
        if (particleSystem != null)
        {
            particleSystem.Play(); // 播放死亡粒子效果
        }

        // 停止敌人移动
        if (navMeshAgent != null)
        {
            navMeshAgent.isStopped = true; // 停止NavMeshAgent的移动
            navMeshAgent.velocity = Vector3.zero; // 防止任何剩余的移动
        }

        // 启动缩小并消失的过程
        StartCoroutine(ScaleDownAndDestroy());
    }
    IEnumerator ScaleDownAndDestroy()
    {
        Vector3 originalScale = transform.localScale; // 记录原始尺寸
        float timeElapsed = 0f;

        // 循环以逐渐缩小敌人
        while (timeElapsed < scaleDownDuration)
        {
            float t = timeElapsed / scaleDownDuration; // 计算插值因子
            transform.localScale = Vector3.Lerp(originalScale, Vector3.zero, t); // 插值缩小
            timeElapsed += Time.deltaTime; // 增加时间经过量
            yield return null; // 等待下一帧
        }

        transform.localScale = Vector3.zero; // 确保最终设置为零
        Destroy(gameObject); // 销毁敌人对象
    }

    IEnumerator UpdatePath()
    {
        while (target != null)
        {
            Vector3 preTarPos = new Vector3(target.position.x, 0, target.position.z);
            navMeshAgent.SetDestination(preTarPos);
            yield return new WaitForSeconds(updateRate);
        }

    }

}

[System.Serializable]
public class Wave
{

    public int enemyNum;
    public float timeBtwSpawn;

}

5.判定击杀与敌人的死亡 

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LivingEntity : MonoBehaviour,IDamageable
{
    public float maxHealth;
   [SerializeField] protected float health;
    protected bool isDead;
    //事件的声明格式:public / private + event key + delegate + evetname (on + Foo );

    public event Action onDeath;
    //private void Start()
    //{
    //    health = maxHealth;
    //}

    protected virtual void Start()//子类可以覆盖,覆写,也可以使用Base.Start
    {
        health = maxHealth;
    }

    //事件的触发,是有事件拥有者的内部逻辑触发的
    protected void Die()
    {
        isDead = true;
        Destroy(gameObject,0.5f);//延迟0.5s销毁对象
        if(onDeath != null)
        {
            onDeath.Invoke();
        }
    }
    //当人物手上的时候扣血,触发内部逻辑中的时间,人物:GameOver ,敌人取消追击
    //敌人: 判断场上剩下还有没有敌人,如果被消灭则开始下一波
    public void TakenDamage(float _damageAmount)
    {
        health -= _damageAmount;
        if (health <= 0 && isDead == false)
        {
            Die();
        }
    }
}

 

internal interface IDamageable
{
    void TakenDamage(float _damageAmount);
}

 粒子死亡动画这个要取消勾选


学习时间:


学习产出:

存储-JoeStudy(提醒自己的)学习资料位置

标签:Vector3,杀怪,void,float,private,Unity,波数,using,public
From: https://blog.csdn.net/2402_83615482/article/details/144055724

相关文章

  • unity四叉树
    1publicclassQuadTree_12{3//节点内允许的最大对象4privateintmaxObjs=1;56//最大层级7privateintmaxLvl=3;89//当前层级10privateintlvl;1112//当前层级内的对象13privateList<Tr......
  • Unity中GameManager的用处
     UnityGameManager是Unity引擎中的一个常见的设计模式,他用于管理游戏中的全局状态和对象。GameManager可以存储和访问游戏中的全局信息,如玩家分数、生命值、游戏困难等等。此外,GameManager还可以管理游戏对象的创建、销毁和更新,比如敌人、道具等。通过使用GameM......
  • Unity版本使用情况统计(更新至2024年11月)
    UWA发布|本期UWA发布的内容是第十五期Unity版本使用统计,统计周期为2024年5月至2024年11月,数据来源于UWA网站(www.uwa4d.com)性能诊断提测的项目。希望给Unity开发者提供相关的行业趋势作为参考。2024年5月-2024年11月版本分布  以近半年的数据统计来看,如图1所示,2022.3的版......
  • 【Unity游戏开发】Plastic SCM Beta版服务到期,将Plastic hub(Plastic SCM Beta版)云端
    目录工作概述项目迁移1.访问团结云平台MigrationPage2.迁移项目连接本地项目1.下载团结云开发app1.1从Hub下载1.2从网页下载2.连接本地项目2.1连接本地项目问题1:找不到本地数据库问题2:提示“当前文件夹已存在工作区”3.成功连接本地项目后更新3.1成功连接本地项目3.2更新项目4.......
  • UnityShaderLab 实现两张图片切换
    实现思路:在顶点着色器中获取物体在世界空间下的某一轴的坐标传递给片元着色器,o.val=v.vertex.x;然后在片元着色器中采样两张图片,根据输入的偏移值的更换两张图片的显示。fixed4t1=tex2D(_MainTex,i.texcoord);fixed4t2=tex2D(_SubTex,i.texcoord1);......
  • unity3d——基础篇2刷(三角函数)
     目录知识点一:弧度与角度的相互转换知识点二:三角函数知识点三:反三角函数代码实现知识点一:弧度与角度的相互转换弧度转角度:使用 Mathf.Rad2Deg 将弧度转换为角度。角度转弧度:使用 Mathf.Deg2Rad 将角度转换为弧度。知识点二:三角函数正弦函数(Sin):Mathf.Sin 计算......
  • [Unity] 【游戏开发】Unity开发基础1-创建Unity项目:从Unity Hub选择合适的渲染管
    创建一个新的Unity项目通常是开发过程中的第一步,而Unity为此提供了强大的工具和灵活的选项。本文将详细介绍如何使用UnityHub创建项目、选择合适的Unity版本、模板和渲染管线,并阐述每种选项的优缺点和适用场景。1.UnityHub:统一管理项目和版本UnityHub是Unity提供的集......
  • Learn to Develop an Inventory System in Unity 6 & Blender
    MP4创建|视频:h264、1280×720|音频:AAC,44.1KHz,2通道类型:在线学习|语言:英语|持续时间:108讲座(15h48m)|大小:11.1GB使用Unity6和Blender制作库存系统:ScriptableObjects,3D资产和交互式UI设计学习内容了解并使用Unity6实现一个有序的库存系统,包括项目类别和自......
  • 【unity小技巧】一些unity3D灯光的使用与渲染及性能优化方案
    文章目录天空盒反射配置太阳耀斑眩光烘培光照烘培光照时弹出错误,记得勾选模型下面的选择阴影项目配置光源模型模型shader的问题全局光照混合光照模式混合照明模式减性照明模式Shadowmask照明模式间接烘焙照明模式环境光遮罩灯光探针反射探针技术关闭反射探针可以修改反......
  • Unity入门需要学点什么?
    1.核心编程与优化C#高级技能熟练使用C#,掌握面向对象编程、泛型、LINQ、异步编程等。UnityAPI精通深入了解Unity生命周期(例如Awake、Start、Update、FixedUpdate)、事件系统、协程、组件架构。性能优化使用Profiler工具分析和优化性能。减少GC(垃圾回收)压力,优化内存分配。熟......