Unity学习笔记(六)使用状态机重构角色移动、跳跃、冲刺
前言
本文为Udemy课程The Ultimate Guide to Creating an RPG Game in Unity学习笔记
整体状态框架(简化)

- Player 是操作对象的类: 继承了 MonoBehaviour 用于定义游戏对象的行为,每个挂载在 Unity 游戏对象上的脚本都需要继承自
MonoBehaviour,才能利用 Unity 的生命周期事件和功能。 - PlayerState 是定义状态接口,这里定义了状态类的 Enter(进入),Update(更新),Exit(退出)
- PlayerStateMachine 是定义上下文类,它持有当前状态的引用,并合适的时机调用状态的行为
ChangeState。 - 具体的状态
- PlayerMoveState(移动状态)
- PlayerJumpState(跳跃状态)
- PlayerIdleState(站立状态)
PlayerState
玩家状态的基类,包含状态的基本操作构造函数和三个基础抽象函数进入状态、更新状态、退出状态。
public class PlayerState
{protected Player3 player;protected PlayerStateMachine stateMachine;protected Rigidbody2D rb;protected float xInput;protected float yInput;public string animBoolName;// 记录状态的开始时间,方便做一些状态的转化protected float stateTimer;protected bool triggerCalled;public PlayerState(Player3 _player, PlayerStateMachine _stateMachine, string _animBoolName){this.player = _player;this.stateMachine = _stateMachine;this.animBoolName = _animBoolName;}public virtual void Enter(){player.anim.SetBool(animBoolName, true);rb = player.rb;triggerCalled = false;}public virtual void Exit() {player.anim.SetBool(animBoolName, false);}public virtual void Update() {stateTimer -= Time.deltaTime;xInput = Input.GetAxisRaw("Horizontal");yInput = Input.GetAxisRaw("Vertical");player.anim.SetFloat("yVelocity", rb.velocity.y);}public virtual void AnimatorFinishTrigger(){triggerCalled = true;}
}
PlayerStateMachine
玩家状态的转换类,改变状态步骤
- 退出当前状态
- 初始化新状态
- 进入新的状态
public class PlayerStateMachine
{public PlayerState currentState { get; private set;}public void Initialize(PlayerState _state){currentState = _state;currentState.Enter();}public void ChangeState(PlayerState _nextState){currentState.Exit();currentState = _nextState;currentState.Enter();}
}
状态类
有两个比较特殊的状态
- PlayerAirState,为了设置玩家在空中时的动作
- PlayerGroundedState,这个状态是为了抽象出玩家站立,跳跃,移动的通用代码。这些状态都要求玩家必须在地面上才能转换。
PlayerAirState(玩家在空中状态)
public class PlayerAirState : PlayerState
{public PlayerAirState(Player3 _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName){}public override void Enter(){base.Enter();}public override void Exit(){base.Exit();}public override void Update(){base.Update();// rb.velocity.y or x 静止时 都为 0,所以不需要关注当前位置,只要静止为0if (player.IsGroundDetected()){stateMachine.ChangeState(player.idleState);}// 跳起来的移动速度会慢一点if (xInput != 0){player.SetVelocity(player.moveSpeed * .8f * xInput, rb.velocity.y);}}
}
PlayerGroundedState(玩家在地面状态)
public class PlayerGroundedState : PlayerState
{public PlayerGroundedState(Player3 _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName){}public override void Enter(){base.Enter();}public override void Exit(){base.Exit();}public override void Update(){base.Update();if (Input.GetKeyDown(KeyCode.Mouse0)){stateMachine.ChangeState(player.moveState);}if (!player.IsGroundDetected()){stateMachine.ChangeState(player.airState);}if (Input.GetKeyDown(KeyCode.Space) && player.IsGroundDetected()){stateMachine.ChangeState(player.jumpState);}}}
PlayerDashState(冲刺状态)
public class PlayerDashState : PlayerState
{public PlayerDashState(Player3 _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName){}public override void Enter(){base.Enter();stateTimer = player.dashDuration;}public override void Exit(){base.Exit();// 冲刺结束后x轴不动,在空中就不会一直移动player.SetVelocity(0, rb.velocity.y);}public override void Update(){base.Update();player.SetVelocity(player.dashSpeed * player.dashDir, 0);if (stateTimer < 0){stateMachine.ChangeState(player.idleState);}}
}
PlayerIdleState(站立状态)
public class PlayerIdleState : PlayerGroundedState
{public PlayerIdleState(Player3 _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName){}public override void Enter(){base.Enter();// 将坐标设置为 0,0player.SetZeroVelocity();}public override void Exit(){base.Exit();}public override void Update(){base.Update();if(xInput != 0){stateMachine.ChangeState(player.moveState);}}
}
PlayerJumpState(跳跃状态)
public class PlayerJumpState : PlayerState
{public PlayerJumpState(Player3 _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName){}public override void Enter(){base.Enter();rb.velocity = new Vector2(rb.velocity.x, player.jumpForce);}public override void Exit(){base.Exit();}public override void Update(){base.Update();if (rb.velocity.y < 0){stateMachine.ChangeState(player.airState);}}
}
PlayerMoveState(移动状态)
public class PlayerMoveState : PlayerGroundedState
{public PlayerMoveState(Player3 _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName){}public override void Enter(){base.Enter();}public override void Exit(){base.Exit();}public override void Update(){base.Update();player.SetVelocity(xInput * player.moveSpeed, rb.velocity.y);if (xInput == 0){stateMachine.ChangeState(player.idleState);}}
}
Player
玩家类,继承自MonoBehaviour,状态机和各类状态等的定义都在这里进行初始化赋值。
我们需要创建一些关键函数:Awark(),Start(),Update()
该方法初始化过程:
暂时无法在飞书文档外展示此内容
下面的类比较复杂,我设置一个简化版和详细版,了解大致流程简化版即可
简化版
public class Player3 : MonoBehaviour
{public Animator anim { get; private set; }public Rigidbody2D rb { 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 PlayerDashState dashState { get; private set; }public PlayerAirState airState { get; private set; }#endregionprivate void Awake(){stateMachine = new PlayerStateMachine();idleState = new PlayerIdleState(this, stateMachine, "Idle");moveState = new PlayerMoveState(this, stateMachine, "Move");dashState = new PlayerDashState(this, stateMachine, "Dash");jumpState = new PlayerJumpState(this, stateMachine, "Jump");airState = new PlayerAirState(this, stateMachine, "Jump");}private void Start(){rb = GetComponent<Rigidbody2D>();anim = GetComponentInChildren<Animator>();stateMachine.Initialize(idleState);}private void Update(){stateMachine.currentState.Update();CheckForDashInput();}
}
详细版
public class Player3 : MonoBehaviour
{public Animator anim { get; private set; }public Rigidbody2D rb { get; private set; }protected int facingDir = 1;protected bool facingRight = true;[Header("Move info")]public float moveSpeed = 12f;public float jumpForce;[Header("Dash info")][SerializeField] private float dashCooldown;private float dashUsageTimer;public float dashSpeed = 5f;public float dashDuration = 5f;public float dashDir { get; private set; }[Header("Collision Info")][SerializeField] protected Transform groundCheck;[SerializeField] protected float groundCheckDistance;[SerializeField] protected LayerMask whatIsGround;#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 PlayerDashState dashState { get; private set; }public PlayerAirState airState { get; private set; }#endregionprivate void Awake(){stateMachine = new PlayerStateMachine();idleState = new PlayerIdleState(this, stateMachine, "Idle");moveState = new PlayerMoveState(this, stateMachine, "Move");dashState = new PlayerDashState(this, stateMachine, "Dash");jumpState = new PlayerJumpState(this, stateMachine, "Jump");airState = new PlayerAirState(this, stateMachine, "Jump");}private void Start(){rb = GetComponent<Rigidbody2D>();anim = GetComponentInChildren<Animator>();stateMachine.Initialize(idleState);}private void Update(){stateMachine.currentState.Update();CheckForDashInput();}// => 可以理解为 简化返回表达式的符号,主要用于单行方法、属性或表达式的定义。public virtual bool IsGroundDetected() => Physics2D.Raycast(groundCheck.position, Vector2.down, groundCheckDistance, whatIsGround);private void CheckForDashInput(){dashUsageTimer -= Time.deltaTime;if (Input.GetKeyDown(KeyCode.LeftShift) && dashUsageTimer < 0){dashUsageTimer = dashCooldown;dashDir = Input.GetAxisRaw("Horizontal");if (dashDir == 0)dashDir = facingDir;stateMachine.ChangeState(dashState);}}public void SetZeroVelocity(){rb.velocity = new Vector2(0, 0);}public void SetVelocity(float _xVelocity, float _yVelocity){rb.velocity = new Vector2(_xVelocity, _yVelocity);FlipController(_xVelocity);}public virtual void FlipController(float _x){if (_x > 0 && !facingRight){Flip();}else if (_x < 0 && facingRight){Flip();}}protected virtual void Flip(){facingDir = facingDir * -1;facingRight = !facingRight;transform.Rotate(0, 180, 0);}
}
小结
使用状态机进行重构我们可以看到,之后如果想新增或者修改状态,只需要去对应状态类中修改即可,不需要在很多地方维护对应代码,对于代码整体也更加清晰。
整体玩家状态机代码重构就是上面,接下来重构玩家动画部分
动画部分重构
重构前,我们是通过维护玩家当前的状态是否来判断是否进入和退出。使用状态机后,我们应该通过状态代表的参数来维护状态机。

重构后,我们可以看到状态机的方式我们不需要通过playerIdle来转换,每次状态机执行完都会进入 Exit 结点(改结点详情看拓展) ,这样我们不用维护状态之间是否有依赖,更方便后续的拓展

重构后效果

拓展
Unity 如何调用 Awake()
Awake() 方法在 Unity 生命周期中的角色
Awake() 是 Unity 中 MonoBehaviour 类的生命周期方法之一,它的主要功能是在对象被创建时初始化脚本和对象状态。它是 Unity 生命周期中非常重要的一个环节。
Awake() 的调用时机
-
在场景加载时:
当一个场景加载完成,所有启用的 GameObject 的组件(脚本)会在它们的Awake()方法中执行初始化。 -
在 GameObject 动态实例化时:
如果一个 GameObject 在运行时被动态创建(如通过Instantiate()方法),其附加的脚本也会在实例化时调用Awake()。 -
调用顺序:
Awake()的调用顺序不受脚本执行顺序的影响。Unity 会按照 GameObject 被加载的顺序来依次调用这些对象的Awake()方法。- 重要:如果有依赖其他对象的初始化,可以将逻辑放在
Start()中,因为Start()会在所有Awake()调用完成之后执行。
Unity 生命周期的完整流程
以下是 Unity 中 MonoBehaviour 的常见生命周期方法及其顺序:
-
脚本的加载和初始化阶段:
Awake()- 在所有脚本的生命周期中最先调用。
- 用于初始化脚本的内部状态,以及为后续使用的变量赋初始值。
- 在
Awake()被调用时,其他组件或 GameObject 可能尚未初始化完成,因此不适合依赖其他对象。
-
脚本的启用阶段:
OnEnable()- 在对象被启用时调用。
- 如果需要在对象启用时执行额外操作,可以在这里添加逻辑。
-
场景运行时初始化阶段:
Start()- 在所有对象的
Awake()方法执行完成后调用。 Start()是初始化逻辑的推荐位置,特别是在需要依赖其他对象的情况下。
- 在所有对象的
-
运行时更新阶段:
Update():每帧调用一次,用于更新逻辑。FixedUpdate():每固定时间间隔调用一次,用于物理计算。LateUpdate():在每帧的所有Update()执行完成后调用,用于执行后续逻辑(例如摄像机跟随)。
-
销毁阶段:
OnDisable()OnDestroy()
Awake() 的作用和特点
1. 作用
-
初始化脚本实例:
用于初始化脚本中的变量和状态,例如分配引用、加载资源、设置默认值等。 -
加载必要的资源:
比如加载外部的材质、音频或配置文件。 -
设置依赖项:
如果某些对象或组件需要在脚本激活时使用,可以在Awake()中获取或初始化它们。
- 与
Start()的区别
Awake()比Start()更早调用。Awake()用于确保脚本自身的初始化,而Start()适合处理与其他对象或组件的交互。
| 特性 | Awake() | Start() |
|---|---|---|
| 调用时机 | 对象加载时立即调用 | 所有对象的 Awake() 执行后 |
| 依赖其他对象状态 | 不建议依赖其他对象 | 可安全地依赖其他对象 |
| 手动调用 | 不推荐(Unity 会自动调用) | 可以在特定情况下手动调用 |
示例:Awake() 与生命周期的关系
using UnityEngine;public class Example : MonoBehaviour
{void Awake(){Debug.Log("Awake: 初始化脚本变量和资源");}void OnEnable(){Debug.Log("OnEnable: 脚本或对象被激活");}void Start(){Debug.Log("Start: 在对象所有的初始化完成后调用");}void Update(){Debug.Log("Update: 每帧调用");}void OnDisable(){Debug.Log("OnDisable: 脚本或对象被禁用");}void OnDestroy(){Debug.Log("OnDestroy: 对象被销毁");}
}
在场景运行时,执行顺序为:
Awake():初始化。OnEnable():对象启用时的逻辑。Start():所有对象的Awake()调用完成后。Update():每帧更新。OnDisable()和OnDestroy():对象被禁用或销毁时。
总结
Awake()的核心作用是初始化脚本变量和状态,在 Unity 生命周期中最早被调用。- 适合场景:用来初始化脚本或 GameObject 的自身逻辑,而不依赖其他对象。
- 与其他方法的关系:
Awake()是生命周期的起点。- 如果依赖其他对象的初始化,建议将逻辑放到
Start()。
希望这些内容能帮助你理解 Unity 的生命周期和 Awake() 方法的作用!如果你有更多问题,随时提问!
Unity 调用 Awake 的简单原理
Unity 调用 Awake() 的原理其实可以简单地理解为以下几个步骤。虽然 Unity 的底层实现细节是封闭的,但我们可以根据其生命周期行为和一些公开信息总结出其大致逻辑。
1. Unity 生命周期的核心
Unity 的生命周期方法(如 Awake()、Start())是由 Unity 引擎在运行时按照特定顺序自动调用的。这些方法不需要开发者手动注册或显式调用。以下是基本的执行流程:
-
场景加载:
- Unity 会加载场景中的所有 GameObject。
- 如果某个 GameObject 上挂载了继承自
MonoBehaviour的脚本,它会参与生命周期流程。
-
脚本扫描和方法检测:
- Unity 会通过反射机制检测脚本中是否实现了特定的生命周期方法(如
Awake())。 - 如果检测到某个生命周期方法,则将其注册到 Unity 的内部执行流程中。
- Unity 会通过反射机制检测脚本中是否实现了特定的生命周期方法(如
-
方法调用:
- 在特定的生命周期阶段(例如场景加载后),Unity 引擎会按顺序调用注册的生命周期方法。
2. 调用 Awake() 的简化原理
以下是 Unity 如何调用 Awake() 的基本逻辑:
步骤 1:场景加载
- 当场景加载时,Unity 会逐一加载场景中的所有 GameObject 和它们的组件。
步骤 2:反射检测
- Unity 扫描每个继承自
MonoBehaviour的脚本,检查是否定义了Awake()方法。- Unity 使用 反射 来动态检测方法是否存在。
- 如果
Awake()存在,Unity 会将该方法存储为一个待调用的任务。
步骤 3:初始化并调用 Awake()
- 在所有 GameObject 被加载到内存后,Unity 会依次调用这些 GameObject 脚本的
Awake()方法。 - 调用顺序:
Awake()是生命周期的第一个阶段。- 只要脚本和对象处于启用状态,
Awake()会在对象加载时立即被调用。
代码实现的简化逻辑
以下是 Unity 调用 Awake() 的简单逻辑,用伪代码表示:
// Unity 内部的场景加载流程
void LoadScene(Scene scene)
{// 1. 加载场景中的所有 GameObjectforeach (GameObject go in scene.gameObjects){// 2. 获取 GameObject 上的所有 MonoBehaviour 脚本foreach (MonoBehaviour script in go.GetComponents<MonoBehaviour>()){// 3. 检查是否实现了 Awake() 方法if (script.HasMethod("Awake")){// 4. 调用 Awake()script.Awake();}}}
}
3. Awake() 的调用特点
-
只调用一次:
Awake()只会在脚本实例初始化时调用一次,无论该脚本的 GameObject 是否被启用或禁用。
-
不依赖脚本执行顺序:
Awake()的调用顺序是按照 GameObject 加载的顺序。- 脚本执行顺序设置对
Awake()无影响。
-
在
Start()之前调用:Awake()是生命周期的第一步,Start()在所有Awake()调用完成后才会被执行。
-
适合自我初始化:
Awake()的设计初衷是用于初始化自身的变量和状态,而不适合依赖其他 GameObject,因为此时其他对象可能尚未完成初始化。
4. 示例代码
以下代码演示了 Unity 如何在场景加载时调用 Awake() 和 Start():
using UnityEngine;public class Example : MonoBehaviour
{void Awake(){Debug.Log("Awake called: 初始化变量");}void Start(){Debug.Log("Start called: 依赖其他对象初始化");}
}
假设场景中有两个 GameObject 分别挂载了该脚本,运行时输出可能是:
Awake called: 初始化变量 (GameObject 1)
Awake called: 初始化变量 (GameObject 2)
Start called: 依赖其他对象初始化 (GameObject 1)
Start called: 依赖其他对象初始化 (GameObject 2)
5. 为什么使用 Awake()
Awake() 的核心作用是初始化自身的状态。例如:
- 分配变量或资源。
- 加载外部数据。
- 设置默认值。
6. 与其他生命周期方法的关系
| 方法名 | 调用时机 | 适合的操作 |
|---|---|---|
Awake() | GameObject 加载到场景时 | 初始化自身变量,不依赖其他对象 |
OnEnable() | GameObject 或脚本启用时 | 运行需要在启用时触发的逻辑 |
Start() | 所有 Awake() 调用完成后,场景运行时 | 初始化需要依赖其他对象的逻辑 |
Update() | 每帧调用 | 持续更新逻辑,例如动画、输入检测 |
总结
Unity 调用 Awake() 的原理可以概括如下:
- 加载场景:
- Unity 会加载所有 GameObject 和其组件。
- 检测方法:
- Unity 使用反射检测脚本是否实现了
Awake()方法。
- Unity 使用反射检测脚本是否实现了
- 方法调用:
- Unity 自动调用实现了
Awake()的脚本,不需要开发者手动调用。
- Unity 自动调用实现了
通过这个流程,Unity 实现了生命周期的动态管理,使得开发者只需专注于脚本逻辑的实现,而不用关心具体的调用机制。
Unity状态机的Exit结点
在Unity的Animator状态机(Animator State Machine)中,Exit结点用于表示从当前状态机退出到其父状态机的状态。以下是关于Exit结点的详细说明:
- Exit结点是什么?
Exit结点是Unity Animator中的一个特殊的状态机结点,它表示一个状态机结束的出口点。通常用于嵌套的子状态机(Sub-State Machine)中,告诉父状态机当前子状态机的行为已经完成,可以切换到父状态机中的其他状态。
- 使用场景
- 嵌套状态机(Sub-State Machines):
当你将一个复杂的动画逻辑封装到一个子状态机中时,Exit结点表示该子状态机完成其逻辑后应该退出,回到父状态机进行下一步。 - 动画流程控制:
如果子状态机处理完某些特定动画(如攻击动作、过渡动画等),可以通过Exit结点返回父状态机,从而进行主流程的继续。
- 如何设置
Exit结点
在Unity中,以下是设置Exit结点的步骤: - 创建子状态机:
在Animator中,右键选择Create Sub-State Machine,创建一个嵌套的子状态机。 - 添加状态和过渡:
在子状态机中添加具体的动画状态(如攻击、跳跃等)。 - 使用
Exit结点:- 在子状态机中,右键选择
Make Transition,并将过渡指向Exit结点。 Exit结点是子状态机的默认出口,不需要手动创建。
- 在子状态机中,右键选择
- 在父状态机中配置逻辑:
在父状态机中,可以设置子状态机到其他状态(或反过来)的过渡逻辑。
4. Exit的行为
- 当动画流转到
Exit结点时,子状态机会退出,控制权回到父状态机。 - 可以通过
Animator Controller中的条件(如布尔值、触发器等)控制子状态机何时退出。 - 在父状态机中,子状态机到
Exit的过渡会被认为完成,可以接着切换到其他状态。
- 注意事项
- 不能直接控制
Exit结点:
Exit是一个逻辑性的特殊结点,它不能像普通状态一样附加动画或行为。 - 父状态机的后续逻辑:
确保在父状态机中正确设置过渡条件,否则子状态机退出后可能进入意料之外的状态。
- 示例场景
假设有一个游戏角色的动画逻辑:
- 父状态机:
包括“待机”、“跑步”、“攻击子状态机”。 - 子状态机(攻击子状态机):
包括“攻击准备”、“攻击动作”、“攻击结束”。
当“攻击动作”完成后,子状态机会通过Exit结点返回父状态机,角色的动画状态可能回到“待机”或其他状态。
相关文章:
Unity学习笔记(六)使用状态机重构角色移动、跳跃、冲刺
前言 本文为Udemy课程The Ultimate Guide to Creating an RPG Game in Unity学习笔记 整体状态框架(简化) Player 是操作对象的类: 继承了 MonoBehaviour 用于定义游戏对象的行为,每个挂载在 Unity 游戏对象上的脚本都需要继承自 MonoBehaviour&#x…...
【C++数据结构——树】二叉树的遍历算法(头歌教学实验平台习题) 【合集】
目录😋 任务描述 相关知识 1. 二叉树的基本概念与结构定义 2. 建立二叉树 3. 先序遍历 4. 中序遍历 5. 后序遍历 6. 层次遍历 测试说明 通关代码 测试结果 任务描述 本关任务:实现二叉树的遍历 相关知识 为了完成本关任务,你需要掌…...
Android Telephony | 协议测试针对 test SIM attach network 的问题解决(3GPP TS 36523-1-i60)
背景 除了运营商实网卡之外,在各种lab的协议测试中需要 follow 3GPP 协议定义(可以查询3gpp.org website 获取),那么 feature 需要支持覆盖的卡就不止运营商本身了。 本文介绍 IA APN流程,重点关注在协议/lab测试中,针对测试卡、非实网卡的的设置项,记录遇到的问题分…...
jenkins入门3 --执行一个小demo
1、新建视图 视图可以理解为是item的集合,这样可以将item分类。新建视频可以选择加入已有的item 2、新建item 1)输入任务名称、选择一个类型,常用的是第一个freestyle project 2)进行item相关配置,general 设置项目名字,描述,参数…...
STM32传感器系列:GPS定位模块
简介 我们在做一些项目的时候,可能需要使用到GPS模块,我们可以通过这个模块获得当前的位置以及时间,我这里就教大家如何去使用GPS定位模块,并且把示例代码开源到评论区下面,有需要自取即可,我我这里用到的…...
技术成长战略是什么?
文章目录 技术成长战略是什么?1. 前言2. 跟技术大牛学成长战略2.1 系统性能专家案例2.2 从开源到企业案例2.3 技术媒体大V案例2.4 案例小结 3. 学习金字塔和刻意训练4. 战略思维的诞生5. 建议 技术成长战略是什么? 1. 前言 在波波的微信技术交流群里头…...
【前端】Vue3与Element Plus结合使用的超详细教程:从入门到精通
文章目录 Moss前沿AI一、教程概述1.1 目标读者1.2 学习目标 二、为什么选择Vue3与Element Plus2.1 Vue3的优势2.2 Element Plus的优势2.3 二者结合的优势 三、环境搭建3.1 创建Vue3项目3.2 安装Element Plus3.3 引入Element Plus 四、Element Plus常用组件使用详解4.1 按钮&…...
Linux 35.6 + JetPack v5.1.4之 pytorch升级
Linux 35.6 JetPack v5.1.4之 pytorch升级 1. 源由2. 升级步骤1:获取二进制版本步骤2:安装二进制版本步骤3:获取torchvision步骤4:安装torchvision步骤5:检查安装版本 3. 使用4. 补充4.1 torchvision版本问题4.2 支持…...
旷视科技C++面试题及参考答案
在 Linux 系统下常用的命令有哪些? 在 Linux 系统中有许多常用命令。首先是文件和目录操作相关的命令。“ls” 命令用于列出目录的内容,它有很多选项,比如 “ls -l” 可以以长格式显示文件和目录的详细信息,包括文件权限、所有者、大小、修改时间等;“ls -a” 则会显示所有…...
C 语言函数指针 (Pointers to Functions, Function Pointers)
C 语言函数指针 {Pointers to Functions, Function Pointers} 1. Pointers to Functions (函数指针)2. Function Pointers (函数指针)2.1. Declaring Function Pointers2.2. Assigning Function Pointers2.3. Calling Function Pointers 3. Jump Tables (转移表)References 1. …...
66.基于SpringBoot + Vue实现的前后端分离-律师事务所案件管理系统(项目 + 论文)
项目介绍 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装律师事务所案件管理系统软件来发挥其高效地信息处理的作用…...
Docker容器中Elasticsearch内存不足问题排查与解决方案
在使用Docker运行Elasticsearch(ES)时,可能会遇到内存不足的问题,导致ES无法启动。以下是一次完整的排查和解决过程。 问题描述 在启动ES时,日志提示如下错误: # Native memory allocation (mmap) failed…...
Ubuntu 下测试 NVME SSD 的读写速度
在 Ubuntu 系统下,测试 NVME SSD 的读写速度,有好多种方法,常用的有如下几种: 1. Gnome-disks Gnome-disks(也称为“Disks”)是 GNOME 桌面环境中的磁盘管理工具,有图形界面,是测试…...
Neo4j的部署和操作
注:本博文展示部署哥操作步骤和命令,具体报告及运行截图可通过上方免费资源绑定下载 一.数据库的部署与配置 在单个节点上对进行数据库的单机部署 (1)上传neo4j-community-3.5.30-unix.tar.gz到hadoop1的/export/so…...
react axios 优化示例
使用 axios 是 React 项目中非常常见的 HTTP 请求库。为了提升 axios 在 React 中的性能、可维护性和用户体验,我们可以从 代码组织、请求优化 和 用户体验优化 多个角度进行详细的优化。 一、安装与基础配置 安装 axios npm install axios创建 Axios 实例 为了更好地管理…...
探索数字化展馆:开启科技与文化的奇幻之旅
在科技飞速发展的当下,数字展馆作为一种新兴的展示形式,正逐渐走进大众的视野。数字展馆不仅仅是传统展馆的简单“数字化升级”,更是融合了多媒体、数字化技术以及人机交互等前沿科技的创新产物。 数字展馆借助VR、AR、全息投影等高科技手段&…...
基于深度学习的视觉检测小项目(七) 开始组态界面
开始设计和组态画面。 • 关于背景和配色 在组态画面之前,先要确定好画面的风格和色系。如果有前端经验和美术功底,可以建立自己的配色体系。像我这种工科男,就只能从网络上下载一些别人做好的优秀界面,然后在photo shop中抠取色…...
AI赋能跨境电商:魔珐科技3D数字人破解出海痛点
跨境出海进入狂飙时代,AI应用正在深度渗透并重塑着跨境电商产业链的每一个环节,迎来了发展的高光时刻。生成式AI时代的大幕拉开,AI工具快速迭代,为跨境电商行业的突破与飞跃带来了无限可能性。 由于跨境电商业务自身特性鲜明&…...
【C/C++】nlohmann::json从文件读取json,并进行解析打印,实例DEMO
使用 json::parse 函数将JSON格式的字符串解析为 nlohmann::json 对象。这个函数支持多种输入源,包括字符串、文件流等。 #include <iostream> #include <nlohmann/json.hpp> #include <fstream>using json nlohmann::json;int main() {// 解析…...
安装Anaconda搭建Python环境,并使用VSCode作为IDE运行Python脚本
下面详细说明如何安装Anaconda搭建Python环境,并使用VSCode作为编辑器运行Python脚本的过程: 1. 下载Anaconda 访问Anaconda的官方网站:https://www.anaconda.com/products/distribution 3. 根据您的操作系统选择适合的版本下载。Anaconda支…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...
Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)
参考官方文档:https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java(供 Kotlin 使用) 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...
AI书签管理工具开发全记录(十九):嵌入资源处理
1.前言 📝 在上一篇文章中,我们完成了书签的导入导出功能。本篇文章我们研究如何处理嵌入资源,方便后续将资源打包到一个可执行文件中。 2.embed介绍 🎯 Go 1.16 引入了革命性的 embed 包,彻底改变了静态资源管理的…...
如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
关于uniapp展示PDF的解决方案
在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项: 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库: npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...
苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会
在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...
