Unity类银河恶魔城学习记录8-2 p78.Improving black with clone creating源代码

news2025/1/12 3:00:43

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考
此代码仅为较上一P有所改变的代码

【Unity教程】从0编程制作【Unity教程】从0编程制作

Blackhole_Hotkey_Controller.cs
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;

public class Blackhole_Hotkey_Controller : MonoBehaviour
{

    private SpriteRenderer sr;
    private KeyCode myHotKey;
    private TextMeshProUGUI myText;

    private Transform myEnemy;
    private Blackhole_Skill_Controller blackHole;


    public void SetupHotKey(KeyCode _myNewHotKey, Transform _myEnemy, Blackhole_Skill_Controller _myBlackHole)
    {

        sr = GetComponent<SpriteRenderer>();
        myText = GetComponentInChildren<TextMeshProUGUI>();

        myEnemy = _myEnemy;
        blackHole = _myBlackHole;

        myHotKey = _myNewHotKey;
        myText.text = myHotKey.ToString();
    }
    public void Update()
    {
        if(Input.GetKeyDown(myHotKey))
        {
            blackHole.AddEnemyToList(myEnemy);

            myText.color = Color.clear;
            sr.color = Color.clear;
        }

    }
}

Blackhole_Skill_Controller.cs
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;

public class Blackhole_Skill_Controller : MonoBehaviour
{
    [SerializeField] private GameObject hotKeyPrefab;
    [SerializeField] private List<KeyCode> KeyCodeList;

    public float maxSize;//最大尺寸
    public float growSpeed;//变大速度
    public bool canGrow;//是否可以变大
    public float shrinkSpeed;//缩小速度
    public bool canShrink;//缩小

    public bool canCreateHotKeys = true;专门控制后面进入的没法生成热键
    private bool cloneAttackReleased;
    public int amountOfAttacks = 4;
    public float cloneAttackCooldown = .3f;
    private float cloneAttackTimer;

    [SerializeField]private List<Transform> targets = new List<Transform>();
    [SerializeField] private List<GameObject> createdHotKey = new List<GameObject>();

    private void Update()
    {
        cloneAttackTimer -= Time.deltaTime;

        if(Input.GetKeyDown(KeyCode.R))
        {
            cloneAttackReleased = true;
            canCreateHotKeys = false;
            DestroyHotKeys();
        }    

        if(cloneAttackTimer < 0 && cloneAttackReleased)
        {
            cloneAttackTimer = cloneAttackCooldown;

            int randomIndex = Random.Range(0, targets.Count);
            
            
            //限制攻击次数和设置攻击偏移量
            float _offset;
            
            if (Random.Range(0, 100) > 50)         
                _offset = 2;
            else
                _offset = -2;

            SkillManager.instance.clone.CreateClone(targets[randomIndex], new Vector3(_offset, 0, 0));
            amountOfAttacks--;


            if(amountOfAttacks <= 0)
            {
                canShrink = true;
                cloneAttackReleased = false;
            }
        }



        if(canGrow&&!canShrink)
        {
            //这是控制物体大小的参数
            transform.localScale = Vector2.Lerp(transform.localScale, new Vector2(maxSize, maxSize), growSpeed * Time.deltaTime);
            //类似MoveToward,不过是放大到多少大小 https://docs.unity3d.com/cn/current/ScriptReference/Vector2.Lerp.html
        }
        if(canShrink)
        {
            transform.localScale = Vector2.Lerp(transform.localScale, new Vector2(0, 0), shrinkSpeed * Time.deltaTime);

            if(transform.localScale.x < 0)
            {
                Destroy(gameObject);
            }
        }
    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.GetComponent<Enemy>()!=null)
        {
            collision.GetComponent<Enemy>().FreezeTime(true);
            CreateHotKey(collision);

        }
    }

    private void CreateHotKey(Collider2D collision)
    {
        if(KeyCodeList.Count == 0)//当所有的KeyCode都被去除,就不在创建实例
        {
            return;
        }

        if(!canCreateHotKeys)//这是当角色已经开大了,不在创建实例
        {
            return;
        }
        
        //创建实例
        GameObject newHotKey = Instantiate(hotKeyPrefab, collision.transform.position + new Vector3(0, 2), Quaternion.identity);

        //将实例添加进列表
        createdHotKey.Add(newHotKey);


        //随机KeyCode传给HotKey,并且传过去一个毁掉一个
        KeyCode choosenKey = KeyCodeList[Random.Range(0, KeyCodeList.Count)];

        KeyCodeList.Remove(choosenKey);

        Blackhole_Hotkey_Controller newHotKeyScript = newHotKey.GetComponent<Blackhole_Hotkey_Controller>();

        newHotKeyScript.SetupHotKey(choosenKey, collision.transform, this);
    }
    public void AddEnemyToList(Transform _myEnemy)
    {
        targets.Add(_myEnemy);
    }

    //销毁Hotkey
    private void DestroyHotKeys()
    {

        if(createdHotKey.Count <= 0)
        {
            return;
        }
        for (int i = 0; i < createdHotKey.Count; i++)
        {
            Destroy(createdHotKey[i]); 
        }

    }
}
Clone_Skill.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Clone_Skill : Skill
{
    [Header("Clone Info")]
    [SerializeField] private GameObject clonePrefab;//克隆原型
    [SerializeField] private float cloneDuration;//克隆持续时间
    [SerializeField] private bool canAttack;// 判断是否可以攻击
    
    public void CreateClone(Transform _clonePosition,Vector3 _offset)//传入克隆位置
    {
        GameObject newClone = Instantiate(clonePrefab);//创建新的克隆//克隆 original 对象并返回克隆对象。
        //https://docs.unity3d.com/cn/current/ScriptReference/Object.Instantiate.html

        newClone.GetComponent<Clone_Skill_Controller>().SetupClone(_clonePosition,cloneDuration,canAttack,_offset);//调试clone的位置,同时调试克隆持续时间
                                                                                                 //Controller绑在克隆原型上的,所以用GetComponents,
                                                                                                
    }
    
}

Clone_Skill_Controller.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//Clone_Skill_Controller是绑在Clone体上的也就是Prefah上的
public class Clone_Skill_Controller : MonoBehaviour
{
    private Animator anim;//声明animator
    private SpriteRenderer sr;//定义Sr
    [SerializeField] private float colorLoosingSpeed;//加速消失时间 

    private float cloneTimer;//定时器
    [SerializeField]private Transform attackCheck;
    [SerializeField] private float attackCheckRadius = .8f;
    private Transform closestEnemy;

    private void Awake()
    {
        sr = GetComponent<SpriteRenderer>();//拿到Sr
        anim = GetComponent<Animator>();//拿到anim
    }
    private void Update()
    {
        cloneTimer -= Time.deltaTime;

        if(cloneTimer < 0)
        {
            sr.color = new Color(1, 1, 1,sr.color.a-(Time.deltaTime * colorLoosingSpeed));//设置sr消失
        }
        if(sr.color.a<0)
        {
            Destroy(gameObject);
        }
    }
    public void SetupClone(Transform _newTransform,float _cloneDuration,bool _canAttack,Vector3 _offset)
    {
        if(_canAttack)
        {                                     
            anim.SetInteger("AttackNumber", Random.Range(1, 3));//返回[minInclusive..maxInclusive](范围包括在内)内的随机浮点值。如果minInclusive大于maxInclusive,则数字会自动交换。
        }                                                       //Random.Range()//https://docs.unity3d.com/cn/current/ScriptReference/Random.Range.html
        transform.position = _newTransform.position+_offset;//这个函数实现了将克隆出来的对象的位置与Dash之前的位置重合的效果
        cloneTimer = _cloneDuration;
        FaceCloseTarget();
    }

    private void AnimationTrigger()
    {
        cloneTimer = -.1f;
    }
    private void AttackTrigger()
    {
        Collider2D[] colliders = Physics2D.OverlapCircleAll(attackCheck.position, attackCheckRadius);//创建一个碰撞器组,保存所有圈所碰到的碰撞器
        //https://docs.unity3d.com/2022.3/Documentation/ScriptReference/Physics2D.OverlapCircleAll.html
        foreach (var hit in colliders)//https://blog.csdn.net/m0_52358030/article/details/121722077
        {
            if (hit.GetComponent<Enemy>() != null)
            {
                hit.GetComponent<Enemy>().Damage();
            }
        }
    }

    private void FaceCloseTarget()
    {
        Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position, 25);//找到环绕自己的所有碰撞器

        float closestDistance = Mathf.Infinity;//正无穷大的表示形式(只读)
        //https://docs.unity3d.com/cn/current/ScriptReference/Mathf.Infinity.html
        foreach(var hit in colliders)
        {
            if(hit.GetComponent<Enemy>()!=null)
            {
                float distanceToEnemy = Vector2.Distance(transform.position, hit.transform.position);//拿到与敌人之间的距离
                if(distanceToEnemy < closestDistance)//比较距离,如果离得更近,保存这个敌人的位置,更改最近距离
                {
                    closestDistance = distanceToEnemy;
                    closestEnemy = hit.transform;
                }
            }
        }

        if(closestEnemy != null)
        {
            if(transform.position.x>closestEnemy.position.x)//敌人在左面,转一圈
            {
                transform.Rotate(0,180,0);
            }
        }

    }
}
PlayerDashState.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerDashState : PlayerState
{   //由Ground进入
    public PlayerDashState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
    {
    }

    public override void Enter()
    {
        base.Enter();
        player.skill.clone.CreateClone(player.transform,new Vector3(0,0,0));//调用克隆函数,并传入当前位置已调试clone的位置
        stateTimer = player.dashDuration;设置Dash可以保持的值
        
    }

    public override void Exit()
    {
        base.Exit();
        player.SetVelocity(0, rb.velocity.y);//当退出时使速度为0防止动作结束后速度不变导致的持续移动

    }

    public override void Update()
    {
        base.Update();
        if(!player.IsGroundDetected()&&player.IsWallDetected())//修复无法在空中dash直接进入wallSlide,修复在wallslide可以dash
                                                               //因为一旦在wallSlide里dash,就会直接进wallSlide,当然还有更简单的方法
        {
            stateMachine.ChangeState(player.wallSlide);
        }
        player.SetVelocity(player.dashSpeed * player.dashDir, 0);//这个写在Update里,防止在x轴方向减速了,同时Y轴写成0,以防止dash还没有完成就从空中掉下去了
        if (stateTimer < 0)当timer小于0,切换
        {
            stateMachine.ChangeState(player.idleState);
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1493410.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Dell R620中文手册下载

poweredge-r620_owners-manual_zh-cn.pdf https://url20.ctfile.com/f/36743220-1030280698-8d9322?p2024 (访问密码: 2024)

为什么我建议你2024年一定要入局鸿蒙?

自去年发布现象级“爆款”手机Mate 60后&#xff0c;华为就备受关注。小灰作为一枚程序员&#xff0c;关注的重心更偏向于技术。华为手机搭载的国产自研的鸿蒙操作系统&#xff08;HarmonyOS&#xff09;&#xff0c;已经成为一个业界的里程碑&#xff0c;是我国国产技术自主化…

ChatGPT Plus 自动扣费失败,如何续订

ChatGPT Plus 自动扣费失败&#xff0c;如何续订 如果您的 ChatGPT Plus 订阅过期或扣费失败&#xff0c;本教程将指导您如何重新订阅。 本周更新 ChatGPT Plus 是一种每月20美元的订阅服务。扣费会自动进行&#xff0c;如果您的账户余额不足&#xff0c;OpenAI 将在一次扣费…

C语言写学生信息管理系统

说明:本博文来自CSDN-问答板块,题主提问。 需要:用C语言设计一个学生信息管理系统(尽量不使用指针),学生信息包括学号,姓名,数学成绩,C语言成绩,英语成绩和每个学生的总成绩这几项。系统要实现如下几个功能:1.添加学生2.删除学生3.修改学生信息4.查询学生信息5进行学…

C#,无监督的K-Medoid聚类算法(K-Medoid Algorithm)与源代码

1 K-Medoid算法 K-Medoid&#xff08;也称为围绕Medoid的划分&#xff09;算法是由Kaufman和Rousseeuw于1987年提出的。中间点可以定义为簇中的点&#xff0c;其与簇中所有其他点的相似度最小。 K-medoids聚类是一种无监督的聚类算法&#xff0c;它对未标记数据中的对象进行聚…

安装/升级 gcc

文章目录 查看当前 gcc 版本查看 yum 软件库 gcc 版本列表下载最新版本安装 查看当前 gcc 版本 查看 yum 软件库 gcc 版本列表 只有一个4.8的版本&#xff0c;过旧 下载最新版本 wget https://ftp.gnu.org/gnu/gcc/gcc-13.2.0/gcc-13.2.0.tar.gz 安装 ./configure 报错 提示…

【深圳五兴科技】Java后端面经

本文目录 写在前面试题总览1、java集合2、创建线程的方式3、对spring的理解4、Spring Boot 和传统 Spring 框架的一些区别5、springboot如何解决循环依赖6、对mybatis的理解7、缓存三兄弟8、接口响应慢的处理思路9、http的状态码 写在前面 关于这个专栏&#xff1a; 本专栏记录…

基于51单片机的电子秒表Protues仿真设计

目录 一、设计背景 二、实现功能 三、仿真结果 四、源程序 一、设计背景 随着科技的不断发展&#xff0c;电子设备在我们生活中扮演着愈加重要的角色。这些电子设备不仅使我们的生活更加便利&#xff0c;还帮助我们提高工作效率和精确度。其中&#xff0c;电子秒表是常用的计…

如何配置JDK的环境变量(简单灵活易懂)

前言&#xff1a; 开始学习java的小伙伴们一定都备一件事困扰过&#xff0c;那就是jdk的环境变量的配置&#xff0c;搞不懂为啥要配置环境变量&#xff0c;到底有啥子用&#xff1f;接下来小编带大家配置一下 配置环境变量的作用&#xff1f; Path&#xff1a;当用javac、jav…

redis 缓存击穿问题(互斥锁,逻辑过期)

1、缓存击穿问题 缓存击穿问题:一个被高并发访问并且缓存重建业务较复杂的key突然失效了&#xff0c;无数的请求访问会在瞬间给数据库带来巨大的冲击。 场景:假设线程1在查询缓存之后&#xff0c;本来应该去查询数据库&#xff0c;然后把这个数据重新加…

Java学习笔记002——类的修饰符

在Java语言中&#xff0c;类的访问修饰符决定了其它类能够访问该类的方式。类有如下4种访问修饰符&#xff0c;在创建类时用于类的声明&#xff1a; 1、public: 当一个类被声明为public时&#xff0c;它可以从任何其他类中被访问&#xff0c;无论这些类位于哪个包中。通常&am…

探索设计模式的魅力:深入解析解释器模式-学习、实现与高效使用的全指南

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;并且坚持默默的做事。 探索设计模式的魅力&#xff1a;解析解释器模式学习、实现与高效使用全指南 文章目录 一、案…

2024大厂Java面试最火问题,1200页文档笔记

前言 ⽂章有点⻓&#xff0c;请耐⼼看完&#xff0c;绝对有收获&#xff01;不想听我BB直接进⼊⾯试分享&#xff1a; 准备过程蚂蚁⾦服⾯试分享拼多多⾯试分享字节跳动⾯试分享最后总结个人所得&#xff08;供大家参考学习&#xff09; 当时我⾃⼰也准备出去看看机会&#…

2024 年广西职业院校技能大赛高职组《云计算应用》赛项赛题第 3 套

#需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; #需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; #需要资源或有问题的&#xff0c;可私博主&#xff01;&#xff01;&#xff01; 某企业根据自身业务需求&…

工业网关、物联网网关与PLC网关是什么?

网关是什么&#xff1f; 网关是一种用于连接不同网络的网络设备&#xff0c;其作用是实现网络之间的通信和数据交换。它负责将一个网络的数据转发到另一个网络&#xff0c;并且可以进行路由、转换和过滤等处理。通常用于连接局域网和广域网之间&#xff0c;可以是硬件设备或者软…

Jenkins如何做到parameter页面里2个参数的联动

在Jenkins中&#xff0c;参数化构建是一种非常有用的功能&#xff0c;它可以让用户在构建过程中输入参数&#xff0c;从而实现更灵活的构建流程。有时候&#xff0c;我们希望两个参数之间能够实现联动&#xff0c;即一个参数的取值会影响另一个参数的取值。要实现这样的功能&am…

蚂蚁感冒c++

题目 思路 “两蚂蚁碰面会掉头&#xff0c;若其中一只蚂蚁感冒了&#xff0c;会把感冒传染给碰到的蚂蚁”&#xff0c;这句话看作是“两蚂蚁碰面会互相穿过&#xff0c;只是把感冒的状态传给了另一只蚂蚁”&#xff0c;因为哪只蚂蚁感冒了并不是题目的重点&#xff0c;重点是有…

iview碰到的一些问题总结

iview tabs嵌套使用问题 tabs嵌套使用的时候不是直接套用行了&#xff0c;直接套用会出现内层tab都集成到一级tab去&#xff0c;需要设置该属性指向对应 Tabs 的 name 字段(需要版本大于3.3.1) <Tabs name"tab1" ><TabPane label"标签1" tab&qu…

springboot基于java的中医院门诊挂号诊断就诊系统ssm+jsp

主要研究内容&#xff1a; 医院门诊挂号系统分为护士&#xff0c;医生&#xff0c;药房&#xff0c;收费&#xff0c;管理员等权限。 护士&#xff1a;挂号、退号、查询病人。挂号——就诊科室(发热门诊、骨科、妇科等等)&#xff0c;就诊医生数据库获取&#xff0c;挂号类型—…

【vue.js】文档解读【day 1】 | 模板语法1

如果阅读有疑问的话&#xff0c;欢迎评论或私信&#xff01;&#xff01; 本人会很热心的阐述自己的想法&#xff01;谢谢&#xff01;&#xff01;&#xff01; 文章目录 模板语法前言文本插值原始HTML属性Attribute绑定动态绑定多个值 模板语法 前言 Vue 使用一种基于 HTML…