virtual的重写能力,,这在剥离Player方法和成员变量的时候,起的作用很灵活,敌人默认可以继承这些规则,但只是默认,自己要修改的话和原来不会产生半点联系,这个确实厉害


Cinemachine Virtual Camera(虚拟相机)
dead zone是红区,soft是蓝区

Bias X和Y是判定区 的移动

damping是控制相机跟随速度

Cinemachine FreeLook 也是 一个虚拟相机(Virtual Camera) ,它的作用和普通的 Cinemachine Virtual Camera 类似,但专门用于 第三人称跟随相机 ,并且提供了 自由旋转 的功能。
就像普通的 Cinemachine Virtual Camera 会被 CinemachineBrain 控制一样,FreeLook 也会被 CinemachineBrain 控制 ,如果它的 优先级更高 ,或者你切换到了它,它就会成为 主相机。
如果你的游戏是 第三人称+玩家自由控制视角 ,那么 FreeLook 是一个很重要的组件。如果你的相机只是 自动跟随角色,那么普通的 Virtual Camera 就够用了,FreeLook 不是必须的。
Extensions(扩展功能)
-
可以添加额外的 Cinemachine 扩展,比如:
- Cinemachine Confiner(限制相机移动范围,适用于 2D 地图)
- Cinemachine Impulse Listener(接收震动事件)
- Cinemachine Collider(防止相机穿墙)
-
目前你没有添加扩展,但如果你想要限制相机范围,可以添加 Confiner。
Noise(相机抖动效果)
- 目前是 None ,说明 相机不会有任何抖动或晃动。
- 如果想要 震动效果 (比如 FPS 游戏里的枪械后坐力、地震效果),可以在这里添加 Perlin Noise。
Aim(相机对准方式)
-
你的设置是 Do Nothing ,意味着 相机不会自动旋转来对准目标,而是保持静态视角。
-
如果想让相机自动看向目标,可以改为 Composer。
-
常见的 Aim 选项:
- Do Nothing(不旋转)
- Composer(智能对准目标)
- Group Composer(用于多个目标)
- Hard Look At(完全锁定目标)
Body(相机的移动模式)
-
你的设置是 Framing Transposer,它的作用是:
- 自动跟随目标,但不会完全锁死目标的位置。
- 允许一定程度的相机偏移和平滑移动,使相机运动更加自然。
-
常见的 Body 模式:
- Framing Transposer(常用于 2D/3D 角色跟随)
- Transposer(适用于自由跟随)
- Hard Lock to Target(完全锁定到目标)
- Dolly Track(用于轨道相机)
-
这个参数很重要!如果你觉得相机跟随不够平滑,可以调整这个选项的参数。
Transitions(过渡)
- 这里可以配置相机切换时的过渡方式,你的设置是默认值,暂时没有特殊过渡
Lens Ortho Size
-
镜头大小 ,这个参数只在 正交投影(Orthographic)模式 下生效,适用于 2D 游戏。
-
你的
Lens Ortho Size = 7.55
,意味着摄像机的视野范围较大。 -
如果是 3D 游戏,这个参数不会影响透视 ,你需要调整 Field of View(FOV) 来控制视角。
Standby Update
-
控制当相机不处于激活状态时的更新方式:
- Always:即使相机不处于激活状态,仍然会更新它的状态(消耗性能)。
- Round Robin (你的设置):Unity 会 轮流更新 非激活相机(平衡性能)。
- Never :非激活相机不会更新,如果你有多个相机,建议用这个 以节省性能。
-
一般不用改,Round Robin 是默认推荐的方式。
Look At(观察目标)
- 你的设置是 None,说明相机不会自动对准某个目标,而是自由移动。
- 如果想让相机始终对准某个物体(比如主角头部、敌人、目标点),可以在这里设置 Transform 目标。
Follow(跟随目标)
- 你的设置是 Player (Transform) ,说明相机会跟随 玩家角色。
- 如果想让相机自动跟随角色,必须在这里指定目标!
Priority(优先级)
-
控制多个 Cinemachine 相机的优先级 ,数值越大,这个相机的优先级越高,CinemachineBrain 就会切换到它。
-
你的相机 Priority=10,意味着如果没有更高优先级的相机,主相机会使用它。
-
相机切换方式:
- 当有多个 Cinemachine 相机时,优先级最高的相机会成为主相机。
- 可以用脚本
vcam.Priority = 20;
提高某个相机的优先级,从而切换相机。
Save During Play
- 是否在 Play 模式下保存修改的参数(默认关闭)。
- 建议保持关闭,避免误操作导致相机参数在退出 Play 模式后被修改。
Game Window Guides(游戏窗口辅助线)✔
- 是否在 Game 视图中显示相机参考框,可以帮助你调整拍摄范围。
- 推荐开启,这样可以更直观地看到相机的拍摄区域。
Status: Live (Solo)
- 当前虚拟相机的状态 :
Live
:表示 这个相机是当前激活的相机,主相机正在跟随它。Solo
:表示你点击了"Solo"模式,只预览这个相机(不会受其他 Cinemachine 相机影响)。
- 一般不需要手动改动,只要知道它的状态是"Live"就行。
Cinemachine Virtual Camera(虚拟相机)
负责定义 Unity 主相机的行为,比如跟随目标、平滑移动、镜头角度等

brain
Events(事件系统)
-
Camera Cut Event :当 相机发生瞬间切换 (Cut)时触发,可以在这里注册事件,比如 播放特效 或 触发 UI。
-
Camera Activated Event :当 相机变为激活状态 时触发,可以用来做 相机切换的回调。
-
目前你的事件列表是 空的,如果你不需要特殊处理,可以不用管。
Default Blend(默认相机切换方式)
-
控制两个相机之间切换时的过渡动画。
-
你的设置是 Ease In Out(默认,平滑过渡) ,并且持续 2 秒。
-
你可以点击下拉菜单更改,比如:
- Cut(瞬间切换,没有过渡)
- Ease In Out(平滑进入和退出,默认)
- Ease In(慢慢进入,瞬间退出)
- Ease Out(瞬间进入,慢慢退出)
- Custom Blend(使用自定义混合曲线)
-
**这个参数很重要!**如果你觉得相机切换太慢/太快,可以调整这里的时间。
lend Update Method(混合更新方式)
- 控制相机切换的插值计算是在 FixedUpdate 还是 LateUpdate 进行。
- 你的设置是 Late Update(适用于大多数情况)。
- 一般不用改,除非 Blend 过渡效果有问题。
Update Method(更新方式)
-
选项:
- Fixed Update(适用于物理计算,如刚体跟随)
- Late Update(默认,适用于大多数情况)
- Smart Update(智能选择合适的更新模式)
-
你的设置是
Smart Update
,这是 Cinemachine 推荐的默认选项。 -
一般不用改,除非相机跟随有问题。
World Up Override
- 设置相机的"世界上方向" ,默认为
None
(即使用 Unity 默认的 Y 轴向上)。 - 只有在 特殊情况下(比如你的游戏是倒置世界,或者有自定义重力方向)才需要修改。
Ignore Time Scale
- 忽略 Time.timeScale ,如果勾选,它可以在
Time.timeScale = 0
(比如游戏暂停时)继续运作。 - 如果你的游戏有暂停功能,建议开启,否则相机可能会卡住。
Show Camera Frustum(✔ 你启用了这个)
- 显示相机的视锥体(Frustum),在 Scene 视图中可以看到相机的拍摄范围。
- 推荐开启,这样可以更直观地看到相机的拍摄范围。
Show Debug Text
- 显示调试信息(勾选后会在屏幕左上角显示当前激活的相机)
Live Camera
- 当前激活的 Cinemachine 相机 (这里是
CM vcam1
)。 - 这个是只读的,表示 目前主相机正在跟随哪一个 Virtual Camera
它是 Cinemachine 系统的核心,负责控制 Unity 主相机(Main Camera),让它根据虚拟相机(Virtual Camera)的规则切换、平滑过渡。

cinemachine
你可以删除 Library
文件夹,然后将项目发送给别人,他们在自己的 Unity 上打开时,Unity 会自动重新生成 Library
文件夹。
不过需要注意几点:
-
重新生成
Library
可能会比较耗时
Library
文件夹包含 Unity 生成的缓存文件(如导入的资源、脚本编译后的.dll
等),删除后会导致 Unity 重新导入所有资源,可能需要较长时间。 -
某些本地缓存数据可能会丢失
如果项目里有使用
Library
里的特定数据(比如一些插件会存临时文件),删除Library
可能会导致这些数据丢失,需要重新配置。
- 如果你要分享 Unity 项目,最好只打包
Assets
、Packages
和ProjectSettings
文件夹。 - 不要删
Packages
,否则别人的 Unity 可能会缺少依赖。 - 用 Git 忽略
Library
,让每个人本地自动生成它。
这样别人打开你的项目时,可以完整加载资源,同时避免 Library
占用过多空间
library文件夹会自动创建,所以打包的话,Library文件夹可以不打
- Tile Palette
-----------角色基本移动控制finish



为什么要动物理的位置,而不是直接动Animation里的锚点位置,按理讲动图片锚点bug会少一点吧
也许是因为用物理改动对于这个游戏后续的互动来讲,问题不大


14.finalize attack state
这里Alex做的主要是,让攻击动作自带物理上的velocity移动,然后不能在攻击之间移动
动用了协程 的等待时间处理primaryAttackState的Exit时留0.15秒不能移动


记录攻击的间隙

Leave some inertia


子状态机,会默认把第一个创建的state作为黄色跳转箭头,无需任何条件就会跳转

这种情况就是一直在transition to self ,因为isattacking=true
所以一直在transition to 第一帧


也就是转换到attack存在exit time,就是等anystate的那个动画播多久才进 exit


这里存在一个问题,就是切换到anyState并不是直接中断当前的状态

所以Alex的这种状态机设置,也无声之间把这种情况给解决了,不需要依靠exit time
dash是用了计时器,才有按一下却可以持续的效果,move是按住才会不变,这样的设计就把attack的完整播放封死了

可能是Triggercalled这个bool变量只被调用了一次,而攻击动画在exit time里,StateMachine里装载的状态又刷新为需要重复播放....

出现了,按一下,却持续播放了两次攻击动画


这个总父类下的machine变量,是控制player状态的播放的
player类里只是做到不停的轮放当前StateMachine 变量里装的State是拿一个,然后update循环检测,实时更新,与状态的切换没有关系,不参与任何状态的条件判断
stateMachine.ChangeState(player.idleState);

也许自然的全写在一个脚本了并不是不可以,但是复杂了之后, 就分子类,划分各个函数了
这样看,Alex的划分就很明确了,,物理变化动画显示,都由player脚本去做
而其他的事情,均剥离给各个独立的state ,或者总的playerState父类里让所有State使用
让bug能以一种更显而易见的方式出现,也可以是框架设计的一环,
setVelocity是暴露给外界state调用的改变自身速度的函数
而把flip翻转的函数控制放入其中,而不是放在player类的Update函数里,减去了无用时的判断
(是Alex的处理手段,,目的是达成游戏的玩法,是制造玩法,也可是封锁玩法)

直接转整个对象的y轴进行反向,,x轴的方向同时也会改变



hot key
state exist


public PlayerState currentState { get;private set;}
相当于文件属性里设置了只读
Alex先直接创建出三个Player 相关的操控脚本,表明存在关键地位

--
总的state machine规划




这家伙还挺幽默


如果继承了Player类,Skeleton如果之后出现的问题,也同样可以一律解决
还同时对新的游戏物体产生了连同检测的作用

是Skeleton检测玩家的函数,射线获取玩家对象,造成伤害,以及加速,设置成攻击状态
然后停下

如果认为剥离现在的Player类,可以对之后的entity子类 代码有更强的控制力,自然是喜欢剥离
继承作用的理解,,在于认为重写一份全新的类,,和把现在写好的剥离出去,哪个会更费时费力
在做出了Player 的单个操控脚本之后,通过继承entity的总类,剥离出所有对象都会需要的属性
让原Player再继承,,这样不会存在代码白写的情况,相反可以让写的很细致的脚本通过自己的剥离,把这套完善的机制 复制到无限个新的 游戏对象(enemy和其他)
--
这个例子真的很好,都写在一个脚本的话,这么多的新添动作
忙于当前动作,而其他动作需要添加条件阻止,就像 fix bucket's holes

对于这种黏墙的处理,通过 Physic Material 2D调整fraction

使用 Collider.IsTouchingLayers
检测碰撞
**Collider.IsTouchingLayers
**允许你直接检查物体的 Collider 是否与 指定层 上的其他物体发生了碰撞。
cs
// 3D 示例:使用 IsTouchingLayers 来检查碰撞
void Update()
{
// 检查当前物体的 Collider 是否与 Ground 层的 Collider 碰撞
if (GetComponent<Collider>().IsTouchingLayers(LayerMask.GetMask("Ground")))
{
Debug.Log("物体与地面碰撞!");
}
}

唐老师表示,automate Thresholds基本都是不勾自己设置
而后面的Compute Threshold更加无关紧要
College Stuff
系统变量是操作系统和应用程序之间的桥梁,它们帮助程序在运行时获取必要的信息。
修改系统变量 ,比如将新安装的应用程序路径添加到 PATH 中,是为了让系统能够识别并执行这些程序。这样,你就可以在任何地方使用它们,无需手动输入完整路径。
系统变量值是否一定要指向"可执行文件"所在的文件夹层级?
-
可执行文件的路径 :虽然通常是指向可执行文件所在的目录 ,但在实际配置时,并不一定要指向某个具体的可执行文件,而是指向包含可执行文件的目录。这是因为操作系统会根据你输入的命令在该目录下查找相应的可执行文件。
比如,Java 的 PATH 配置 可能只包含
C:\Program Files\Java\jdk1.8.0_161\bin
,因为 Java 可执行文件(如java.exe
、javac.exe
)都位于该目录下,操作系统会自动在这个目录下查找文件。 -
不要求精确到文件:你并不需要在 PATH 中列出每个可执行文件的完整路径,只需要列出包含这些可执行文件的目录。操作系统会自动识别该目录中的可执行文件。
例如,假设有一个安装在
C:\MyApp
目录下的程序MyApp.exe
,你只需要将C:\MyApp
加入到 PATH 中,而不必指定完整路径C:\MyApp\MyApp.exe
。
比如
Myapp / layer1 / layer2 / app.exe
我系统变量的值是Myapp/layer1也可以

关于另一个要配置的系统变量Path(连接命令行的使用)
Path才是更主要的
在 PATH
环境变量中,出现的 %系统变量名%
是环境变量的占位符。
这种方法让你不需要手动填写绝对路径,能够使设置变得更加灵活和通用。也就是说,使用这种变量占位符后,即使你的系统路径有变,程序仍然能够正确找到所需的文件。
如果你在 PATH
环境变量中直接写明了绝对路径 ,通常情况下就不需要额外配置相关的系统变量了
但与此同时,也就失去了动态调整地址的能力,比如要更新的话,绝对路径一直是这个样,但是文件夹的名字就更新了,你就需要再来改一次,之后更新几次,你就改几次