Unity类银河恶魔城学习记录7-9 P75 Saw spin sword源代码

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

【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili

Sword_Skill_Controller.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Sword_Skill_Controller : MonoBehaviour
{[SerializeField] private float returnSpeed = 12;private bool isReturning;private Animator anim;private Rigidbody2D rb;private CircleCollider2D cd;private Player player;private bool canRotate = true;[Header("Piece info")][SerializeField] float pierceAmount;[Header("Bounce info")][SerializeField]private float bounceSpeed;//设置弹跳速度private bool isBouncing;//判断是否可以弹跳private int bounceAmount;//弹跳的次数public List<Transform> enemyTargets;//保存所有在剑范围内的敌人的列表private int targetIndex;//设置targetIndex作为敌人计数器[Header("Spin info")]private float maxTravelDistance;//最大攻击距离private float spinDuration;//持续时间private float spinTimer;//计时器private bool wasStopped;//是否停止private bool isSpinning;private float hitTimer;private float hitColldown;private float spinDirection;//用来不断推进剑在x轴上移动的值private void Awake(){anim = GetComponentInChildren<Animator>();rb = GetComponent<Rigidbody2D>();cd = GetComponent<CircleCollider2D>();}public void ReturnSword(){rb.constraints = RigidbodyConstraints2D.FreezeAll;//修复剑只要不触碰到物体就无法收回的bug//rb.isKinematic = false;transform.parent = null;isReturning = true;}public void SetupSword(Vector2 _dir,float _gravityScale,Player _player){player = _player;rb.velocity = _dir;rb.gravityScale = _gravityScale;if(pierceAmount <= 0)anim.SetBool("Rotation", true); //其次在pierceAmount > 0时不启动旋转动画spinDirection = Mathf.Clamp(rb.velocity.x, -1, 1);用来不断推进剑在x轴上移动的值//Mathf.Clamp,当剑使向右飞的时候,direction为1,反之为-1//https://docs.unity3d.com/cn/current/ScriptReference/Mathf.Clamp.html}public void SetupBounce(bool _isBouncing,int _bounceAmount){isBouncing = _isBouncing;bounceAmount = _bounceAmount;}public void SetupPierce(int _pierceAomunt){pierceAmount = _pierceAomunt;}public void SetupSpin(bool _isSpinning, float _maxTravelDistance,float _spinDuration,float _hitCooldown){isSpinning = _isSpinning;maxTravelDistance = _maxTravelDistance;spinDuration = _spinDuration;hitColldown = _hitCooldown;}private void Update(){if (canRotate)transform.right = rb.velocity;//使武器随着速度而改变朝向if (isReturning){transform.position = Vector2.MoveTowards(transform.position, player.transform.position, returnSpeed * Time.deltaTime);//从原来的位置返回到player的位置//并且随着时间增加而增加速度if (Vector2.Distance(transform.position, player.transform.position) < 1)//当剑与player的距离小于一定距离,清除剑{player.CatchTheSword();}}BounceLogic();SpinLogic();}private void SpinLogic(){if (isSpinning)//首先当isSpining为true才可进入{if (Vector2.Distance(player.transform.position, transform.position) > maxTravelDistance)//当剑与角色到达最大攻击距离,stop为true,停止剑运动,给剑一个倒计时{StopWhenSpinning();}if (wasStopped)//当stop为true,倒计时过了,回归角色{spinTimer -= Time.deltaTime;                                                                    //spinDirection一直是1或者-1,但position是变化的transform.position = Vector2.MoveTowards(transform.position, new Vector2(transform.position.x + spinDirection, transform.position.y), 1.5f * Time.deltaTime);//让剑在x轴上移动的函数if (spinTimer < 0){isReturning = true;isSpinning = false;}hitTimer -= Time.deltaTime;if (hitTimer < 0){hitTimer = hitColldown;Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position, 1);foreach (var hit in colliders){if (hit.GetComponent<Enemy>() != null){hit.GetComponent<Enemy>().Damage();}}}}}}private void StopWhenSpinning(){wasStopped = true;rb.constraints = RigidbodyConstraints2D.FreezeAll;spinTimer = spinDuration;}private void BounceLogic(){if (isBouncing && enemyTargets.Count > 0){transform.position = Vector2.MoveTowards(transform.position, enemyTargets[targetIndex].position, bounceSpeed * Time.deltaTime);//3.当可以弹跳且列表内数量大于0,调用ToWords,这将使剑能够跳到敌人身上if (Vector2.Distance(transform.position, enemyTargets[targetIndex].position) < .1f){enemyTargets[targetIndex].GetComponent<Enemy>().Damage();targetIndex++;bounceAmount--;//设置弹跳次数if (bounceAmount <= 0){isBouncing = false;isReturning = true;}//这样会使当弹跳次数为0时,返回到角色手中if (targetIndex >= enemyTargets.Count){targetIndex = 0;}}//利用与目标距离的判断,使剑接近目标距离时切换到下一个目标。//且如果所有目标都跳完了,切回第一个}}private void OnTriggerEnter2D(Collider2D collision)//传入碰到的物体的碰撞器{if (isReturning){return;}//修复在返回时扔出时没有碰到任何物体,但返回时碰到了物体导致剑的一些性质发生改变的问题,及回来的时候调用了OnTriggerEnter2Dcollision.GetComponent<Enemy>()?.Damage();//设置一下敌人受击动画SetupTargetsForBounce(collision);StuckInto(collision);}//打开IsTrigger时才可使用该函数private void SetupTargetsForBounce(Collider2D collision){if (collision.GetComponent<Enemy>() != null)//首先得碰到敌人,只有碰到敌人才会跳{if (isBouncing && enemyTargets.Count <= 0){Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position, 10);foreach (var hit in colliders){if (hit.GetComponent<Enemy>() != null){enemyTargets.Add(hit.transform);}}}}}//https://docs.unity3d.com/cn/current/ScriptReference/Collider2D.OnTriggerEnter2D.htmlprivate void StuckInto(Collider2D collision){if(pierceAmount > 0 && collision.GetComponent<Enemy>()!= null)//本质就是能穿过敌人,在amount>0时不执行能让剑卡在敌人里的语句就行{pierceAmount--;return;}if (isSpinning){StopWhenSpinning();return;}//防止卡在敌人身上canRotate = false;cd.enabled = false;//相当于关闭碰撞后触发函数。//https://docs.unity3d.com/cn/current/ScriptReference/Collision2D-enabled.htmlrb.isKinematic = true;//开启物理学反应 https://docs.unity3d.com/cn/current/ScriptReference/Rigidbody2D-isKinematic.htmlrb.constraints = RigidbodyConstraints2D.FreezeAll;//冻结所有移动if (isBouncing&&enemyTargets.Count>0)//修复剑卡不到墙上的bugreturn;//终止对动画的改变和终止附在敌人上transform.parent = collision.transform;//设置sword的父组件为碰撞到的物体anim.SetBool("Rotation", false);}}

Sword_Skill.cs
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public enum SwordType
{Regular,Bounce,Pierce,Spin
}public class Sword_Skill : Skill
{public SwordType swordType = SwordType.Regular;//创建应一个enum列表,后面用来判断切换状态[Header("Bounce Info")][SerializeField] private int bounceAmount;[SerializeField] private float bounceGravity;[Header("Pierce info")][SerializeField] private int pierceAmount;[SerializeField] private float pierceGravity;[Header("Skill Info")][SerializeField] private GameObject swordPrefab;//sword预制体[SerializeField] private Vector2 launchForce;//发射力度[SerializeField] private float swordGravity;//发射体的重力[Header("Spin info")][SerializeField] private float hitCooldown = .35f;//攻击冷却[SerializeField] private float maxTravelDistance = 7;//最大攻击距离[SerializeField] private float spinDuration = 2;//持续时间[SerializeField] private float spinGravity = 1;[Header("Aim dots")][SerializeField] private int numberOfDots;//需要的点的数量[SerializeField] private float spaceBetweenDots;//相隔的距离[SerializeField] private GameObject dotPrefab;//dot预制体[SerializeField] private Transform dotsParent;//不是很懂private GameObject[] dots;//dot组private Vector2 finalDir;protected override void Start(){base.Start();GenerateDots();//生成点函数SetupGravity();}private void SetupGravity()//每个剑的状态都对应了不同的剑重力{if(swordType == SwordType.Pierce){swordGravity = pierceGravity;}if(swordType == SwordType.Bounce){swordGravity = bounceGravity;}if(swordType == SwordType.Spin){swordGravity = spinGravity;}}protected override void Update(){base.Update();if (Input.GetKeyUp(KeyCode.Mouse1)){finalDir = new Vector2(AimDirection().normalized.x * launchForce.x, AimDirection().normalized.y * launchForce.y);//将位移量改为单位向量分别与力度的x,y相乘作为finalDir}if (Input.GetKey(KeyCode.Mouse1)){for (int i = 0; i < dots.Length; i++){dots[i].transform.position = DotsPosition(i * spaceBetweenDots);//用循环为每个点以返回值赋值(传入值为每个点的顺序i*点间距}}}public void CreateSword(){GameObject newSword = Instantiate(swordPrefab, player.transform.position, transform.rotation);//创造实例,初始位置为此时player的位置Sword_Skill_Controller newSwordScript = newSword.GetComponent<Sword_Skill_Controller>();//获得Controllerif(swordType == SwordType.Bounce){newSwordScript.SetupBounce(true, bounceAmount);}else if(swordType == SwordType.Pierce){newSwordScript.SetupPierce(pierceAmount);}else if(swordType == SwordType.Spin){newSwordScript.SetupSpin(true, maxTravelDistance, spinDuration,hitCooldown);}newSwordScript.SetupSword(finalDir, swordGravity, player);//调用Controller里的SetupSword函数,给予其速度和重力和player实例player.AssignNewSword(newSword);//调用在player中保存通过此方法创造出的sword实例DotsActive(false);//关闭点的显示}#region Aim regionpublic Vector2 AimDirection(){Vector2 playerPosition = player.transform.position;//拿到玩家此时的位置Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);//https://docs.unity3d.com/cn/current/ScriptReference/Camera.ScreenToWorldPoint.html//大概就是返回屏幕上括号里的参数的位置,这里返回了鼠标的位置//拿到此时鼠标的位置Vector2 direction = mousePosition - playerPosition;//获得距离的绝对向量return direction;//返回距离向量}public void DotsActive(bool _isActive){for (int i = 0; i < dots.Length; i++){dots[i].SetActive(_isActive);//设置每个点是否显示函数}}private void GenerateDots()//生成点函数{dots = new GameObject[numberOfDots];//为dot赋予实例数量for (int i = 0; i < numberOfDots; i++){dots[i] = Instantiate(dotPrefab, player.transform.position, Quaternion.identity, dotsParent);//对象与世界轴或父轴完全对齐//https://docs.unity3d.com/cn/current/ScriptReference/Quaternion-identity.htmldots[i].SetActive(false);//关闭dot}}private Vector2 DotsPosition(float t)//传入顺序相关的点间距{Vector2 position = (Vector2)player.transform.position +new Vector2(AimDirection().normalized.x * launchForce.x,AimDirection().normalized.y * launchForce.y) * t  //基本间距+ .5f * (Physics2D.gravity * swordGravity) * (t * t)//重力影响;//t是控制之间点间距的return position;//返回位置}//设置点间距函数#endregion
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT信号槽实现分析

1.宏定义 qt中引入了MOC来反射&#xff0c;编译阶段变成 MOC–>预处理–>编译–>汇编–>链接 1-1、Q_OBJECT 这个宏定义了一系列代码&#xff0c;包括元对象和处理的函数 #define Q_OBJECT \public: \QT_WARNING_PUSH \Q_OBJECT_NO_OVERRIDE_WARNING \static c…

设计模式(二)单例模式的七种写法

相关文章设计模式系列 面试的时候&#xff0c;问到许多年轻的Android开发他所会的设计模式是什么&#xff0c;基本上都会提到单例模式&#xff0c;但是对单例模式也是一知半解&#xff0c;在Android开发中我们经常会运用单例模式&#xff0c;所以我们还是要更了解单例模式才对…

汇编语言与接口技术实践——秒表

1. 设计要求 基于 51 开发板,利用键盘作为按键输入,将数码管作为显示输出,实现电子秒表。 功能要求: (1)计时精度达到百分之一秒; (2)能按键记录下5次时间并通过按键回看 (3)设置时间,实现倒计时,时间到,数码管闪烁 10 次,并激发蜂鸣器,可通过按键解除。 2. 设计思…

音视频技术-电脑连接调音台时交流声的产生与消除

当电脑&#xff08;笔记本/台式机&#xff09;声卡通过音频线与调音台&#xff08;或扩音机&#xff09;连接时&#xff0c;能听到“交流声”。有时很轻微&#xff0c;有时很明显&#xff0c;甚至干扰正常的演讲或发言。 很多时候&#xff0c;我们在台上演讲时&#xff0c;都会…

模拟、排序(归并排序)算法

模拟、排序算法 一、模拟例题1、错误票据题目信息思路题解 2、回文日期题目信息思路方法一&#xff1a;暴力做法方法二&#xff1a;优化解法 题解方法一&#xff1a;暴力求解方法二&#xff1a;优化解法 二、排序例题1、归并排序题目信息思路题解 一、模拟 例题 1、错误票据 …

springboot222学生网上选课系统的设计与实现

学生网上选课系统的设计与实现 摘 要 如今社会上各行各业&#xff0c;都喜欢用自己行业的专属软件工作&#xff0c;互联网发展到这个时候&#xff0c;人们已经发现离不开了互联网。新技术的产生&#xff0c;往往能解决一些老技术的弊端问题。因为传统学生选课信息管理难度大&…

MDC500-16-ASEMI工业电机专用MDC500-16

编辑&#xff1a;ll MDC500-16-ASEMI工业电机专用MDC500-16 型号&#xff1a;MDC500-16 品牌&#xff1a;ASEMI 正向电流&#xff08;Id&#xff09;&#xff1a;500A 反向耐压&#xff08;VRRM&#xff09;&#xff1a;1600V 正向浪涌电流&#xff1a;600A 正向电压&a…

MATLAB Function转C代码实战

文章目录 前言1. 准备工作2. 使用MATLAB Coder2.1 确定输入输出的类型2.2 MATLAB Coder过程 3. 代码调整和优化4. 编译和测试5. 性能分析和优化结语 前言 在科学与工程领域&#xff0c;MATLAB&#xff08;Matrix Laboratory&#xff09;是一种广泛使用的高级技术计算软件&…

【C之·预处理器】

系列文章目录 文章目录 前言一、预处理指令1. #line的用法1.1 概述 2. #error2.1 概述 二、示例1. #line2. #error 总结 前言 C 预处理器不是编译器的组成部分&#xff0c;但是它是编译过程中一个单独的步骤。简言之&#xff0c;C 预处理器只不过是一个文本替换工具而已&#x…

从0到1入门C++编程——08 函数模板和类模板

文章目录 函数模板1.函数模板基本语法2.函数模板使用的注意事项3.函数模板案例——数组排序4.普通函数和函数模板的区别5.普通函数和函数模板的调用规则6.模板的局限性 类模板1.类模板2.类模板和函数模板的区别3.类模板中成员函数创建时机4.类模板对象做函数参数5.类模板与继承…

飞机订票系统

飞机订票系统 获取源码——》公主号&#xff1a;计算机专业毕设大全

Sora背后团队大揭秘!天才00后?

现在世界上最受关注的技术团队是哪一支&#xff1f; Sora 团队&#xff0c;已经来到聚光灯中心。 不仅项目负责人评论区被挤爆&#xff0c;成了&#x1d54f;最火“景点” 。 当 OpenAI 出手发布 Sora 之后&#xff0c;给人一种降维打击的感觉 —— 效果和之前的技术相比高出…