当前位置: 首页 > news >正文

Unity类银河恶魔城学习记录7-5 p71 Improving sword throwing state源代码

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

 

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

Sword_Skill.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Sword_Skill : Skill
{[Header("Skill Info")][SerializeField] private GameObject swordPrefab;//sword预制体[SerializeField] private Vector2 launchForce;//发射力度[SerializeField] private float swordGravity;//发射体的重力private Vector2 finalDir;//发射方向[Header("Aim dots")][SerializeField] private int numberOfDots;//需要的点的数量[SerializeField] private float spaceBetweenDots;//相隔的距离[SerializeField] private GameObject dotPrefab;//dot预制体[SerializeField] private Transform dotsParent;//不是很懂private GameObject[] dots;//dot组protected override void Start(){base.Start();GenerateDots();//生成点函数}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>();//获得ControllernewSwordScript.SetupSword(finalDir,swordGravity,player);//调用Controller里的SetupSword函数,给予其速度和重力和player实例player.AssignNewSword(newSword);//调用在player中保存通过此方法创造出的sword实例DotsActive(false);//关闭点的显示}public 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;//返回位置}//设置点间距函数
}

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;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;anim.SetBool("Rotation", true);}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();}}                                                                                                       }private void OnTriggerEnter2D(Collider2D collision)//传入碰到的物体的碰撞器{if(isReturning){return;}//修复在返回时扔出时没有碰到任何物体,但返回时碰到了物体导致剑的一些性质发生改变的问题,及回来的时候调用了OnTriggerEnter2DcanRotate = 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;//冻结所有移动transform.parent = collision.transform;//设置sword的父组件为碰撞到的物体anim.SetBool("Rotation", false);}//打开IsTrigger时才可使用该函数//https://docs.unity3d.com/cn/current/ScriptReference/Collider2D.OnTriggerEnter2D.html
}
Player.cs
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;public class Player : Entity
{[Header("Attack Details")]public Vector2[] attackMovement;//每个攻击时获得的速度组public float counterAttackDuration = .2f;public bool isBusy{ get; private set; }//防止在攻击间隔中进入move//[Header("Move Info")]public float moveSpeed;//定义速度,与xInput相乘控制速度的大小public float jumpForce;public float swordReturnImpact;//在player里设置swordReturnImpact作为击退的参数[Header("Dash Info")][SerializeField] private float dashCooldown;private float dashUsageTimer;//为dash设置冷却时间,在一定时间内不能连续使用public float dashSpeed;//冲刺速度public float dashDuration;//持续时间public float dashDir { get; private set; }#region 定义Statespublic PlayerStateMachine stateMachine { get; private set; }public PlayerIdleState idleState { get; private set; }public PlayerMoveState moveState { get; private set; }public PlayerJumpState jumpState { get; private set; }public PlayerAirState airState { get; private set; }public PlayerDashState dashState { get; private set; }public PlayerWallSlideState wallSlide { get; private set; }public PlayerWallJumpState wallJump { get; private set; }public PlayerPrimaryAttackState primaryAttack { get; private set; }public PlayerCounterAttackState counterAttack { get; private set; }public PlayerAimSwordState aimSword { get; private set; }public PlayerCatchSwordState catchSword { get; private set; }public SkillManager skill { get; private set; }public GameObject sword{ get; private set; }//声明sword#endregionprotected override void Awake(){base.Awake();stateMachine = new PlayerStateMachine();//通过构造函数,在构造时传递信息idleState = new PlayerIdleState(this, stateMachine, "Idle");moveState = new PlayerMoveState(this, stateMachine, "Move");jumpState = new PlayerJumpState(this, stateMachine, "Jump");airState = new PlayerAirState(this, stateMachine, "Jump");dashState = new PlayerDashState(this, stateMachine, "Dash");wallSlide = new PlayerWallSlideState(this, stateMachine, "WallSlide");wallJump = new PlayerWallJumpState(this, stateMachine, "Jump");//wallJump也是Jump动画primaryAttack = new PlayerPrimaryAttackState(this, stateMachine, "Attack");counterAttack = new PlayerCounterAttackState(this, stateMachine, "CounterAttack");aimSword = new PlayerAimSwordState(this,stateMachine, "AimSword");catchSword = new PlayerCatchSwordState(this, stateMachine, "CatchSword");//this 就是 Player这个类本身}//Awake初始化所以State,为所有State传入各自独有的参数,及animBool,以判断是否调用此动画(与animatoin配合完成)protected override void Start(){base.Start();stateMachine.Initialize(idleState);skill = SkillManager.instance;}protected override void Update()//在mano中update会自动刷新但其他没有mano的不会故,需要在这个updata中调用其他脚本中的函数stateMachine.currentState.update以实现 //stateMachine中的update{base.Update();stateMachine.currentState.Update();//反复调用CurrentState的Update函数CheckForDashInput();}public void AssignNewSword(GameObject _newSword)//保持创造的sword实例的函数{sword = _newSword;}public void CatchTheSword()//通过player的CatchTheSword进入,及当剑消失的瞬间进入{stateMachine.ChangeState(catchSword);Destroy(sword);}public IEnumerator BusyFor(float _seconds)//https://www.zhihu.com/tardis/bd/art/504607545?source_id=1001{isBusy = true;yield return new WaitForSeconds(_seconds);isBusy = false;}//p39 4.防止在攻击间隔中进入move,通过设置busy值,在使用某些状态时,使其为busy为true,抑制其进入其他state//IEnumertor本质就是将一个函数分块执行,只有满足某些条件才能执行下一段代码,此函数有StartCoroutine调用public void AnimationTrigger() => stateMachine.currentState.AnimationFinishTrigger();//从当前状态拿到AnimationTrigger进行调用的函数public void CheckForDashInput(){if (IsWallDetected()){return;}//修复在wallslide可以dash的BUGif (Input.GetKeyDown(KeyCode.LeftShift) && skill.dash.CanUseSkill())//将DashTimer<0 的判断 改成DashSkill里的判断{dashDir = Input.GetAxisRaw("Horizontal");//设置一个值,可以将dash的方向改为你想要的方向而不是你的朝向if (dashDir == 0){dashDir = facingDir;//只有当玩家没有控制方向时才使用默认朝向}stateMachine.ChangeState(dashState);}}//将Dash切换设置成一个函数,使其在所以情况下都能使用}
PlayerAimSwordState.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//从地面状态进入
public class PlayerAimSwordState : PlayerState
{public PlayerAimSwordState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName){}public override void Enter(){base.Enter();player.skill.sword.DotsActive(true);}public override void Exit(){base.Exit();player.StartCoroutine("BusyFor", .2f); //设置角色在瞄准后的一瞬间和拿回剑的一瞬间时不能移动}public override void Update(){base.Update();player.SetZeroVelocity();//修复原来跑动的速度会被带进aim里的bugif (Input.GetKeyUp(KeyCode.Mouse1))//放开右键,投出{stateMachine.ChangeState(player.idleState);}Vector2 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);//拿到鼠标位置if(player.transform.position.x > mousePosition.x&&player.facingDir == 1)//根据鼠标位置与玩家的位置关系调用Flip函数{player.Flip();}else if(player.transform.position.x < mousePosition.x && player.facingDir == -1){player.Flip();}}
}
PlayerCatchSwordState.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//通过player的CatchTheSword进入,及当剑消失的瞬间进入
public class PlayerCatchSwordState : PlayerState
{private Transform sword;public PlayerCatchSwordState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName){}public override void Enter(){base.Enter();sword = player.sword.transform;//通过player里的sword拿到剑的位置,作者创建了另一个Transform sword的来保存player里的swordif (player.transform.position.x > sword.position.x && player.facingDir == 1)//和aim里一样的调用Flip函数{player.Flip();}else if (player.transform.position.x < sword.position.x && player.facingDir == -1){player.Flip();}rb.velocity = new Vector2(player.swordReturnImpact * -player.facingDir, rb.velocity.y);//用rb.velocity设置速度即可(不用SetVelocity因为这回导致角色翻转,而角色只是朝着面向的反方向移动}public override void Exit(){base.Exit();player.StartCoroutine("BusyFor", .1f); //设置角色在瞄准后的一瞬间和拿回剑的一瞬间时不能移动}public override void Update(){base.Update();if(triggerCalled == true)//通过triggerCalled控制退出进入idleState,及catch动画结束退出{stateMachine.ChangeState(player.idleState);}}
}

相关文章:

  • HCIA-HarmonyOS设备开发认证V2.0-内核扩展组件
  • Linux第57步_“linux系统镜像”和“根文件系统”重新打包小结
  • Llama-Factory的baichuan2微调
  • 2000-2021年县域指标统计数据库
  • Python编程-二万字浅谈装饰器原理与装饰器设计模式和函数式编程案例讲解
  • linux的make和makefile
  • 第三节 zookeeper基础应用与实战2
  • 单片机的省电模式及策略
  • FileZilla Server 1.8.1内网搭建
  • MySQL 基础知识(一)之数据库和 SQL 概述
  • BUUCTF misc 专题(47)[SWPU2019]神奇的二维码
  • 【初始C++】引用的概念及使用场景、引用与指针的区别、内联函数、类型推导关键字auto、范围for循环、指针空值nullptr
  • Excel+VBA处理高斯光束
  • 毕业设计vue+php幼儿园网站系统yl567
  • 【Java EE初阶十二】网络编程TCP/IP协议(二)
  • 收藏网友的 源程序下载网
  • 【JavaScript】通过闭包创建具有私有属性的实例对象
  • 【Redis学习笔记】2018-06-28 redis命令源码学习1
  • Android框架之Volley
  • el-input获取焦点 input输入框为空时高亮 el-input值非法时
  • Laravel Mix运行时关于es2015报错解决方案
  • Vue 2.3、2.4 知识点小结
  • Vue全家桶实现一个Web App
  • 程序员该如何有效的找工作?
  • 每个JavaScript开发人员应阅读的书【1】 - JavaScript: The Good Parts
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 如何将自己的网站分享到QQ空间,微信,微博等等
  • 软件开发学习的5大技巧,你知道吗?
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 微信如何实现自动跳转到用其他浏览器打开指定页面下载APP
  • ​第20课 在Android Native开发中加入新的C++类
  • # Java NIO(一)FileChannel
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • #DBA杂记1
  • (31)对象的克隆
  • (LeetCode) T14. Longest Common Prefix
  • (板子)A* astar算法,AcWing第k短路+八数码 带注释
  • (保姆级教程)Mysql中索引、触发器、存储过程、存储函数的概念、作用,以及如何使用索引、存储过程,代码操作演示
  • (翻译)Entity Framework技巧系列之七 - Tip 26 – 28
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (附源码)ssm高校升本考试管理系统 毕业设计 201631
  • (附源码)基于ssm的模具配件账单管理系统 毕业设计 081848
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (考研湖科大教书匠计算机网络)第一章概述-第五节1:计算机网络体系结构之分层思想和举例
  • (亲测成功)在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机(ubuntu server版本)...
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (三分钟了解debug)SLAM研究方向-Debug总结
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • (转载)VS2010/MFC编程入门之三十四(菜单:VS2010菜单资源详解)
  • (转载)在C#用WM_COPYDATA消息来实现两个进程之间传递数据
  • ***检测工具之RKHunter AIDE
  • **python多态
  • .a文件和.so文件
  • .NET Conf 2023 回顾 – 庆祝社区、创新和 .NET 8 的发布