看到群友提到,于是突然意识到,后天就是2025年了,于是写一写年度总结吧。
总的来说,2024年对我来说还是比较重要的一个年份,从年初到年末自己发生了很多变化,不过这些变化是偏好的:变得更成熟、更冷静了,更加独立了。2024年初的我,总是处在焦虑迷茫、精神内耗中,精神状态和心理状态堪忧——当然这都是年初的事情了。感觉大概10-11月份期间,我就像突然长大了好多岁,已经不会再迷茫、再焦虑、内耗和emo了;我看待事物,也是慢慢有了自己的见解,不是只听别人说。慢慢有了自己的规划和思考,不再“随大流”;我能专心下来做属于我自己的事情,面对问题我也冷静了许多、而不是再逃避。等等许多,让我明显感觉到我的层次貌似又上升了一个阶段。
在知识方面,我24年相比以往还是有很大进步的,我开始认真学习了C#编程语言、在7月份开始自学Unity,并已经坚持到现在了。我的个人博客也发生了很大的变化,以前我喜欢写一些自己的思考、生活的琐事,现在打开基本都是Unity、前端等东西,gal测评都没怎么写过,好处是我什么时候忘了东西、不会了能看我自己写的博客,我完全当成笔记来记录东西。此外,今年还学习了一些go、we ...
起因是某天刷b站,想起来自己还没把up主离忧夏天的C#数据结构看完,结果意外发现了另一位up主木子喵neko,虚拟up+可爱声音讲解数据结构与算法,于是跟着看了。我自身对知识有比较强的分享欲和记录欲(因为我发现我不记笔记总是会忘掉),于是记录一下木子喵算法小课堂第一课:汉诺塔问题。用我最熟悉的C#语言来写。
问题介绍
汉诺塔问题是一个经典的递归问题,源自一个古老的印度传说。在这个问题中,我们有三根柱子和一系列不同大小的圆盘,这些圆盘最初按大小顺序堆叠在一根柱子上。目标是将所有圆盘移动到另一根柱子上,遵循两个规则:一次只能移动一个圆盘,且在移动过程中较大的圆盘不能放在较小的圆盘上面。
***
解题思路
这道题主要思想还是递归(说实话我现在递归还学得挺烂的),我们把柱子做好标记:A柱是起始柱,B柱是中间柱,C柱是目标柱。
形象的图片
我们假设有n个圆盘,从上到下编号为1-n,我们先假设我们通过某种手段,把上面的n-1个圆盘搬到了B柱子,接下来我们把A中剩下的一个盘子搬到了C
那么现在的情况是什么?B柱变成起始柱了,A柱变成中间柱了,按照上面的方法,我们把n-2个圆盘移动到了A柱,B柱剩下 ...
今天在和朋友聊天时,朋友说我变化好大。我电脑上的QQ音乐正好在播放《水仙》专辑的曲子,于是想起了以片冈智为代表的的猫猫社的《水仙》系列作品,对我倒是有一定的影响的。
最先接触《水仙》这部作品,是在一个Q群的精华消息看到:“网页版玩Galgame《水仙》,链接xxxxx”,当时是22年,我读高二,点进去玩。最先多是不太理解,只是能感到作品氛围的悲伤吧,草草玩了第一部作品。
真正开始有所感触、并认真体验《水仙》全系列,是在23年上大学后。当时高考结束,自己在专业上与家里人产生分歧,当时诊出心理疾病、闹得厉害,算是我到现在最不如意的一年。23年经历了很多事,再玩《水仙》时,就很有感触了:对家人的愧疚感、对死亡的不现实感、负罪感等等,算是感同身受。印象深刻的是玩片冈智的小短篇《1980》和《1993》时,因为是片冈智写得确确实实发生在他身边的故事,感觉共鸣感挺强的。
要说我最喜欢的一部,应该是水仙十周年纪念版的《水仙:堇》了吧,这作是最有感触和代入感的一部,因为感觉,故事的主人公高坂堇和我真得太像了,玩起来满是无力感和悲伤吧。当时我状态最差,也经常打开这部作品玩,可以说,高坂堇算是我过去人 ...
本文用于记录伤害检测,算是一套比较完整的伤害检测系统。人物有两个属性,一个是生命值、一个体力值,当体力值小于10时是格挡不了的。那么姑且开始写代码吧。
思路分析
首先我们需要做伤害判定——判断敌人是否受伤害,那就用Physics.SphereCast方法,角色往前一段距离进行一个碰撞检测,声明一个Transform变量currentEnemy = hit.collider.transform,用来保存敌人数据。如果检测到了,并且我们进行了攻击,就可以执行敌人受伤或是格挡的逻辑了。
在写逻辑前,我们可以优化一下,一般游戏都有锁敌机制。我们也写一套锁敌机制,锁敌机制判断条件有二,一是敌人和我们的距离小于1.3,二是敌人在我们前方60度的角度内可以索敌。距离判断很简单,直接Vector3.Distance().magnitude就可以了;角度判断用Vector3.Dot(this,transform.forwar,(currentenemy.transform.position - this.transform.position)),返回一个float值,当其大于根号3/2时可以索敌(点积的 ...
今天上b站,看到了up主NowPaper老师关于Unity连招的思路,觉得代码写得很简洁、同时实现了预输入,觉得很有借鉴意义。
思路介绍
NowPaper老师整体的思路是,先声明InputType来存储输入类型,InputType == 1为轻击输入、InputType == 2为重击输入,结合InputSystem来判断输入类型。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778//声明两个数组来存储轻击和重击动画//这点我觉得其实鬼鬼鬼ii做的简单技能编辑器效果要更好,关于技能编辑器参考我的文章“Unity基础连招思路”public AnimationClip[] Attack1Clips;public AnimationClip[] Attack2Clips;......//以下是根据InputSystem配置好的,判断攻击类型的。in ...
今天试着自己实现了简单的连招系统,先来介绍一下该系统的逻辑:角色按左键是轻攻击、右键是重攻击,重攻击四组、轻攻击三组动画。根据轻攻击连按次数+右键的点击打出不同的重攻击。
技能编辑器
首先做一个最基础的属性编辑器,用ScriptableObject做,为每一个攻击动画配置好我们需要的参数:
1234567891011121314151617using UnityEngine;[CreateAssetMenu(fileName = "ComboData", menuName = "Scriptable Objects/ComboData")]public class ComboData : ScriptableObject{ [SerializeField, Header("招式名称")] private string comboName; [SerializeField, Header("招式伤害")] private int comboDamage; [SerializeFi ...
如今的Unity提供官方写好的缓存池,但我还是打算讲讲自定义缓存池怎么写。
缓存池用途
在射击游戏中,游戏中存在着频繁的子弹创建和销毁工作。如果内存大量频繁地创建和销毁物体,势必会带来很明显的卡顿和性能开销。游戏开发者思考,我是不是可以重复利用固定几个物体、减少内存浪费和性能开销?于是有了缓存池。
思路
以射击游戏为例,先去思考怎么实现子弹缓存效果,我的想法是,场上能看见的子弹也就五、六个,射出去的子弹超出玩家视野后、进行重复利用。于是分类:子弹类——子弹1、子弹2、子弹3、子弹4...
然而缓存池不一定只有子弹类,可能还有炮弹类、垃圾类等等,最后划分大概是这样的一张图表:
物体
子弹类
炮弹类
垃圾类
...
子弹二
炮弹二
垃圾二
...
子弹三
炮弹三
垃圾三
...
这就类似于我们的衣柜,衣柜里有不同的抽屉,每个抽屉里放着不同的衣服,于是联想到字典和List,用Dictionary<string,Queue>来存储
1234567891011121314151 ...
这几天我在试图学习Unity里的动作系统,了解到“有限状态机”这个东西,之前一直有听说过,以前总感觉很高大上,花了一节水课的时间大概弄懂了,于是分享一下。
温馨提示:在开始阅读本文之前,请确保你了解C#语言中接口、继承、抽象类等相关知识点,否则可能会看不懂)。
什么是有限状态机?
对于玩家和怪物,总会存在几个状态:比如待机、跑步、攻击、巡逻...这些都可以称之为状态。我们在Unity开发中最常接触的有限状态机就是我们的Animator窗口——它就是一个有限状态机。
使用有限状态机,可以更方便我们去进行人物行为动作管理和逻辑管理,比如玩家处于待机状态,按下W键切换到跑步状态、跳跃时进入跳跃状态,我们把不同状态用状态机进行管理,就会好很多。
通用的有限状态机框架
在我观看数位、海内海外的博主的视频,发现他们都会采用同一套框架,逻辑、代码都是极其相似的,于是进行总结。
首先我们新建一个名为IState.cs:
12345678using UnityEngine;public interface IState{ public void Enter(); public v ...
本版本是对有限状态机的优化,并讲了有限状态机的具体使用,要比之前的版本更好。主要是借鉴了博主向宇it的文章。
一、编写框架
首先我们新建一个Parameter.cs,用于存储我们怪物的各种参数,比如动画啊、伤害啊,并加上[Serializable]属性使其可以编辑。
1234567891011[Serializable]public class Parameter{ //定义我们需要的参数 public Animator animator; public float attack; public NavMeshAgent nav; public AnimatorStateInfo animatorStateInfo;//当前动画信息 public float idleTime; public Transform targetObj;}
之后写一个IState.cs脚本,我们所有的状态都要继承它,相等于一个规范
12345678public abstract class IState{ protected ...
今天做ACT小demo时,打算给角色做一个八方向移动+跟随相机旋转的功能,结果遇到神奇的bug:按下s键时、角色旋转180度面向摄像机倒着跑,按下ad键则是旋转90度。先展示我的代码,大家可以看看,能不能看出来我的bug
12345678910111213private void CharacterRotation(){ //防止其他动作、如受伤也旋转 if (_HasInput && animator.AnimationAtTag("Move")) { //获得目标旋转角度 playerRotation = cameraTrans.eulerAngles.y + Mathf.Atan2(Speed.x,Speed,y) * Mathf.Rad2Deg; //过渡一下 float rotation = Mathf.SmoothDampAngle(this.transform.eulerAngles.y, playerRotation, ref curren ...