news 2026/10/7 13:15:04

Unity 3D入门实战:从角色移动到敌人AI与多平台构建

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Unity 3D入门实战:从角色移动到敌人AI与多平台构建

很多 Unity 开发者在入门中期会陷入同一种状态:场景会搭了,材质会换了,脚本也能挂上去了,但一运行就出各种“怪毛病”——角色按下方向键不动,或者原地抽搐;明明有碰撞体,角色还是穿墙;敌人站在那里,怎么都不追击玩家。表面看是不同功能出了问题,实际上根因是一样的:把 C# 脚本、输入系统、物理组件、AI 寻路和多平台构建当成孤立知识点学,却没有建立它们之间的协作关系。

这篇文章是 Unity 3D 游戏开发入门实战的下半篇,重点从“搭场景”转向“让场景真正动起来”。读完你会理解 Unity 生命周期中各个方法的调用时机,角色移动应该写在哪里,碰撞体与触发器如何配合,敌人如何用导航网格追击玩家,以及完成一个小游戏后如何在 Windows、Android、WebGL 等平台构建发布。全文保持入门向,但会把原理讲透,让你后续自己扩展功能时不再全靠试错。

这里想先说一个明确判断:Unity 入门阶段最重要的不是记住更多按钮和 API,而是学会用“组件协作”的思维方式看问题。只要把输入、物理、脚本调用这三条关系理清,入门阶段常见的抖动、穿墙、AI 不响应等问题会消失大半。接下来直接用完整案例带你走一遍链路,先看清整体关系,再动手写代码。

1. 先理清 Unity 开发里那张“关系网”

Unity 的场景编辑器看起来很“可视化”,拖拽、点击、改参数就能做出很多效果。但这只是表象。Hierarchy 窗口里的每个游戏对象,本质是一系列组件的容器,而 C# 脚本本身也是一种组件。真正驱动游戏运行的,不是你在编辑器里看到的那张平面图,而是组件之间的事件调用和数据交换。

以最常规的角色控制为例,一张最小协作网是这样构成的:

  • 输入系统:读取键盘、手柄或触摸屏的输入,转换成数值交给脚本。
  • 角色脚本:把输入值转成移动方向,决定角色该往哪走。
  • 刚体组件(Rigidbody):由物理引擎接管角色的位置和速度变化,避免开发者直接改 Transform 造成抖动或穿墙。
  • 碰撞体组件(Collider):告诉物理引擎“这个对象占用多少空间”,以及与其他碰撞体接触时发生什么。
  • 相机脚本:跟随角色位置并调整观察方向。

这里最大的误解是:很多新手认为“角色的位置应该由脚本直接改 Transform”。这个思路在简单 2D 小游戏中可以凑合,但到了 3D 物理场景,一旦对象挂上了 Rigidbody,物理引擎就认为位置和速度应该由它接管。如果你在同一帧里反复改 transform.position,物理引擎同时又在更新刚体状态,角色就会抖动或表现异常。Unity 官方在这方面的建议很明确:对带刚体的对象,尽量通过 AddForce、velocity 等物理接口改变运动,而不是直接改 Transform。

另一个容易被忽略的概念是生命周期调用关系。Update 每帧执行,和帧率绑定;FixedUpdate 按固定时间步执行,通常用于物理运算。如果你在 Update 里改变刚体速度,而物理引擎在同一固定时间步里处理碰撞,两者会出现不同步。这块理解不到位,后面写移动、写跳跃都会遇到诡异现象。

所以这个章节的核心目标,是先建立一张心智地图:脚本是数据加工器,物理组件是执行器,输入是信号源,构建流程是最后一道关卡。凭借这张地图进入下面的实践,效率会高很多。

2. 环境准备与项目结构规划

动手写脚本之前,先把工程环境调整一下,能省掉后期大量因版本、导入和目录混乱导致的麻烦。

Unity 编辑器版本建议使用较新的 Unity 6 或 Unity 2022 LTS 之后的版本。本文示例使用传统输入接口 Input.GetAxis,这是目前网上大量教程仍然采用的方式,也最适合新手先跑通逻辑。如果你的 Unity 版本启用了新版 Input System,在 Project Settings > Player > Active Input Handling 中可以选择 Both,让新旧输入系统同时可用。如果只选择 Input System Package,传统写法会直接报“Input 已过时”或编译错误。

项目结构方面,建议在 Assets 下建立固定目录,不要把所有资源堆在根目录。下面是推荐结构:

Assets/ ├── Scenes/ # 场景文件 ├── Scripts/ # C# 脚本 ├── Prefabs/ # 预制体 ├── Materials/ # 材质 ├── Models/ # 模型资源 └── Textures/ # 贴图资源

很多初学者习惯把脚本直接挂在对象上,文件也乱放,项目小的时候没感觉,场景一复杂就会出现脚本丢失引用、插件目录冲突的问题。建议从第一天就建立目录规范。后续导入第三方资源和插件时,也不要让 Assets 根目录失控。

测试场景可以复用上一篇文章创建的地形或房间。为了演示本章内容,需要一个平整地面、一个角色胶囊体、一个立方体或球体作为收集物。角色建议由一个空物体和子模型组成,比如创建一个名为 Player 的空物体,下面放置 Capsule 子物体。这样后续修改模型、调整碰撞体和挂载脚本都比较清晰。搭建完成后,在 Project 窗口把场景保存到 Scenes 目录。

在 Scripts 目录右键创建 C# Script 时,文件名建议和类名保持一致。如果文件名叫 PlayerMovement.cs,类名自动为 PlayerMovement。不要在创建后随意改名字,否则会触发“类与文件不一致”的编译错误。

3. C# 脚本生命周期:每个方法该放什么代码

Unity 的 C# 脚本不需要手动 new 对象。编辑器会在场景加载时自动实例化挂在游戏对象上的 MonoBehaviour 脚本,并在特定时机调用对应方法。理解这些调用时机,比记住几十个 API 更重要。

常用生命周期方法只有这几个:

方法调用时机典型用途
Awake对象创建时立即调用获取组件引用、初始化私有字段
OnEnable对象或脚本被启用时调用开启监听、订阅事件
Start第一次 Update 前调用设置初始状态,引用外部对象
Update每帧调用处理输入、动画状态、普通判断
FixedUpdate固定时间间隔调用处理刚体、物理碰撞逻辑
LateUpdate所有 Update 执行之后调用相机跟随、后处理类逻辑

新手常常纠结:既然 Update 每帧调用,为什么刚体移动要写到 FixedUpdate?因为物理引擎的模拟步长是固定的,默认固定时间步约为 0.02 秒,也就是每秒 50 次。帧率则会随硬件波动,可能是 60 帧、120 帧甚至更低。如果移动逻辑跟着帧率跑,而物理引擎按固定步长跑,两个系统的数据就会互相干扰。刚体位置变化由物理引擎推演,自然应该与它的模拟步长对齐。

下面是一个生命周期演示脚本,注意每个方法里的代码说明:

// 文件路径:Assets/Scripts/LifecycleDemo.cs using UnityEngine; public class LifecycleDemo : MonoBehaviour { private Rigidbody rb; private float counter; private void Awake() { rb = GetComponent<Rigidbody>(); Debug.Log("Awake 调用"); } private void Start() { Debug.Log("Start 调用"); } private void Update() { counter += Time.deltaTime; transform.Rotate(0f, 30f * Time.deltaTime, 0f); } private void FixedUpdate() { // 对刚体施力请放在这里 if (rb != null) { rb.AddForce(Vector3.down * 0.5f, ForceMode.Acceleration); } } private void LateUpdate() { // 摄像机跟随通常会写在这里 } }

运行场景后,Console 窗口会依次打印 Awake 和 Start 调用信息,你可以直观感受顺序。另一个要点是:如果脚本 A 在 Awake 中初始化数据,脚本 B 在 Start 中引用这些数据,顺序通常是安全的。反之,如果在 Awake 里引用其他脚本在 Start 中初始化的字段,很可能拿到空引用。稳妥做法是在自己的 Awake 里获取自身组件,在 Start 里获取外部对象或管理器。

4. 角色移动控制:输入、刚体与相机配合

这一节真正开始实现一个可在场景里走动的角色。输入部分采用传统 Input Manager,Input.GetAxis("Horizontal") 和 Input.GetAxis("Vertical") 已经经过大量项目验证,适合入门。后续需要手柄、触摸屏或虚拟按键时,再切换到新 Input System 也不冲突。

PlayerMovement 脚本的核心思路是:在 Update 中读取输入并计算目标移动方向,在 FixedUpdate 中把方向转换成刚体速度并处理角色转向。不要直接在 Update 里改 Transform,这是避免抖动和物理异常的关键。

// 文件路径:Assets/Scripts/PlayerMovement.cs using UnityEngine; [RequireComponent(typeof(Rigidbody))] public class PlayerMovement : MonoBehaviour { [Header("移动参数")] public float moveSpeed = 5f; public float rotationSpeed = 720f; private Rigidbody rb; private Vector3 moveDirection; private void Awake() { rb = GetComponent<Rigidbody>(); } private void Update() { float h = Input.GetAxis("Horizontal"); float v = Input.GetAxis("Vertical"); moveDirection = new Vector3(h, 0f, v).normalized; } private void FixedUpdate() { if (moveDirection.magnitude < 0.01f) { rb.velocity = new Vector3(0f, rb.velocity.y, 0f); return; } Vector3 targetVelocity = moveDirection * moveSpeed; rb.velocity = new Vector3(targetVelocity.x, rb.velocity.y, targetVelocity.z); Quaternion targetRotation = Quaternion.LookRotation(moveDirection, Vector3.up); transform.rotation = Quaternion.RotateTowards( transform.rotation, targetRotation, rotationSpeed * Time.deltaTime ); } }

代码里有几个关键点值得注意。第一,moveDirection 做了 normalized 处理,否则斜向移动时速度会变成 1.414 倍,移动速度会明显比横向或纵向更快。第二,rb.velocity 在赋值时保留了 Y 轴速度,如果不保留,角色会在落地瞬间丢失重力速度,跳跃和下坡表现都会异常。第三,旋转使用 RotateTowards 而不是直接赋角度,让转身有一定过渡,手感更自然。这套设计的本质是速度控制,而不是位移控制,后续扩展跳跃、冲刺、掉落都更容易。

给 Player 物体挂载 Rigidbody 和 Capsule Collider。Rigidbody 的 Use Gravity 保持勾选,Interpolate 建议设置为 Interpolate,能减少渲染抖动。Capsule Collider 的中心和高度要尽量贴合角色模型,不要让碰撞体明显小于或大于视觉模型。

相机跟随脚本放在 LateUpdate 里。因为 LateUpdate 在所有 Update 和动画处理之后执行,此时玩家位置已经更新,相机再移动过去,不会出现角色已经移动而相机还停在上一帧位置的割裂感。参考实现如下:

// 文件路径:Assets/Scripts/CameraFollow.cs using UnityEngine; public class CameraFollow : MonoBehaviour { [Header("跟随目标")] public Transform target; [Header("偏移量")] public Vector3 offset = new Vector3(0f, 2.5f, -4f); public float smoothSpeed = 8f; private void LateUpdate() { if (target == null) return; Vector3 desiredPosition = target.position + offset; transform.position = Vector3.Lerp( transform.position, desiredPosition, smoothSpeed * Time.deltaTime ); transform.LookAt(target.position + Vector3.up * 1.2f); } }

把脚本挂到相机上,将 Player 物体拖到 Target 字段。运行场景后使用 WASD 或方向键,观察角色是否正常移动和转向。如果发现角色一直下沉或侧翻,通常是 Collider 没有包住模型,或者 Rigidbody 的 Constraints 没有设置好。对于只在地面行走的角色,勾选 Constraints 中 Freeze Rotation X/Y/Z,可以防止撞到障碍物时角色被物理引擎翻倒。

5. 物理系统:碰撞体、触发器与力的用法

物理系统是入门阶段最容易混淆的部分,因为“碰撞检测”和“触发器触发”看起来相似,内部机制却完全不同。碰撞体是空间几何体的抽象,刚体是物理引擎对物体运动状态的描述。当两个碰撞体接触时,引擎会产生碰撞事件;如果把一个碰撞体标记为 Is Trigger,它就不再参与物理阻挡,只负责探测进出事件。

碰撞体之间的典型用法是角色与地面的接触。角色胶囊体与地面碰撞时,物理引擎阻止角色穿透;碰到墙壁时会被挡下。这要求两个 Collider 都有效,并且至少一方带 Rigidbody。角色移动用速度控制,碰撞结果交给物理引擎处理,脚本里不要试图在 OnCollisionEnter 中手动纠正位置,否则会造成位置跳变。

触发器最典型的设计是金币收集。把金币的 Box Collider 设置为 Is Trigger,脚本接收 OnTriggerEnter 事件。触发事件要求双方中至少一方带 Rigidbody,否则不会触发。参考实现:

// 文件路径:Assets/Scripts/CoinPickup.cs using UnityEngine; public class CoinPickup : MonoBehaviour { [Tooltip("该金币增加的分数")] public int scoreValue = 1; private void OnTriggerEnter(Collider other) { if (other.CompareTag("Player")) { // 实际项目中通常调用 GameManager.Instance.AddScore(scoreValue) Debug.Log($"玩家拾取了金币,增加 {scoreValue} 分"); Destroy(gameObject); } } }

使用 CompareTag 之前,记得在 Tag Manager 中创建 Player 标签,并把角色物体的 Tag 设置为 Player。如果忘记了,拾取事件永远不会进入 if 分支。Tag 名称拼写不一致也是新手经常遇到的坑。

关于力的使用,Unity 的 AddForce 提供多种 ForceMode:ForceMode.Force 是持续力,受质量影响;ForceMode.Impulse 是一瞬间的冲击力,适合开炮、跳跃;ForceMode.Acceleration 直接给加速度,忽略质量;ForceMode.VelocityChange 直接改变速度,忽略质量,适合特殊效果。初学者最容易困惑的是 Force 与 Impulse 的数值受刚体质量影响,同样一个冲量,质量不同的物体速度变化不同。如果两个角色需要跳得不一样高,不要只调力的大小,先检查质量参数。

物理事件的方法名也有明显区别:OnCollisionEnter 需要双方都是非触发器状态,OnTriggerEnter 用于触发器场景。不要混淆,否则会出现“方法写了但始终不触发”的情况。如果拿不准,先看 Inspector 中 Collider 的 Is Trigger 是否勾选,再决定写哪个事件。

验证物理逻辑时,可以在 Window > Analysis > Physics Debugger 中打开刚体与碰撞体的可视化。很多看起来“穿墙”的问题,其实是 Collider 尺寸调得太小,模型看着很大,但碰撞区域很小,两者不匹配。

6. 简易敌人 AI:NavMeshAgent 与追击逻辑

游戏 AI 可以拆成三部分:感知、决策、运动。入门项目中感知用距离判断,决策只做“是否追击”,运动交给导航网格。Unity 的 NavMeshAgent 是处理 3D 寻路的核心组件,它基于预烘焙的 NavMesh 数据计算从当前位置到目标点的可行路径,并自动避障。

使用 NavMeshAgent 之前,需要先烘焙导航网格。在场景中选择产生阻挡的物体,如墙壁、地板、障碍物,打开 Window > AI > Navigation 窗口。在 Bake 页签设置 Agent Radius、Agent Height 等参数,点击 Bake。烘焙完成后,地面会被蓝色网格覆盖,这就是 AI 可行走的区域。烘焙参数决定了寻路的精细程度,Agent Radius 如果设置太小,寻路会贴近墙边,角色容易卡在转角处。

给敌人物体添加 NavMeshAgent 组件后,设置 Speed、Angular Speed、Stopping Distance 等参数。Stopping Distance 表示 AI 逼近目标但还没撞上目标时就会停下的距离。如果设置为 0,敌人会一直顶着玩家模型。

下面是一套最基本的敌人追击逻辑:玩家进入检测范围后开始追击,离开范围后停止。

// 文件路径:Assets/Scripts/EnemyAI.cs using UnityEngine; using UnityEngine.AI; [RequireComponent(typeof(NavMeshAgent))] public class EnemyAI : MonoBehaviour { [Header("AI 参数")] public Transform playerTarget; public float detectionRange = 8f; public float loseRange = 12f; private NavMeshAgent agent; private bool isChasing; private void Awake() { agent = GetComponent<NavMeshAgent>(); } private void Update() { if (playerTarget == null) return; float distance = Vector3.Distance(transform.position, playerTarget.position); if (!isChasing && distance <= detectionRange) { isChasing = true; } else if (isChasing && distance > loseRange) { isChasing = false; } if (isChasing) { agent.isStopped = false; agent.SetDestination(playerTarget.position); } else { agent.isStopped = true; } } }

这个实现最值得学习的点,是把进入范围和离开范围拆成两个数值,形成滞回区间。这样做可以防止敌人站在临界距离时反复切换追击和取消追击,造成视觉上的抽搐行为。“判断状态”和“执行行为”被分开了,Update 先计算状态,再根据状态控制寻路代理,逻辑更清晰。

运行验证时,把 Player 物体拖到 EnemyAI 的 playerTarget 字段。玩家靠近敌人后,敌人从静止立刻转为追击;玩家远离超过 loseRange 后,敌人停在当前位置。地形复杂时,还要注意玩家站立的位置有没有被烘焙进 NavMesh。如果玩家站在未烘焙的平台,NavMeshAgent 无法算出路径,敌人会停在原地。可以在 Scene 窗口直接查看导航网格覆盖范围,并留意 Inspector 中 NavMeshAgent 的 remainingDistance 属性,判断代理是否在正常工作。

7. 多平台构建:Windows、Android、WebGL

Unity 被称为跨平台引擎,得益于成熟的构建管线。一套场景、一套脚本,通过 Build Settings 配置即可输出 Windows、Android、WebGL 等平台的版本。但“一套代码到处构建”不意味着完全不管平台差异,渲染特性、输入方式和性能约束都不同。

打开 File > Build Settings,在 Platform 列表选择目标平台。切换平台时,Unity 会重新导入一部分资源,耐心等待即可。以 Windows 为例,选择后点击 Build,指定输出目录,Unity 会生成 exe 文件和同名数据目录。这两个部分缺一不可,发布时需同时提供。如果想打包成单个可执行文件,需要用第三方工具把数据目录合并进 exe。

构建 Android 前需要确认几项配置。在 Player Settings > Android 中填写 Package Name,例如 com.example.firstgame,设置 Minimum API Level。Unity 默认使用 IL2CPP 后端构建 Android,首次构建耗时较长,而且需要本机安装 Android SDK、NDK 和 JDK。更常见的问题是 Android Build Support 模块没有安装。如果 Build Settings 无法切换到 Android 目标,回 Unity Hub 的 Modules 中安装 Android Build Support,包含 SDK、NDK 和 OpenJDK。

WebGL 平台的构建逻辑也很有特点。WebGL 目标不能完全依赖编辑器里的 Play 模式,部分浏览器端功能需要在真实浏览器中验证。实际执行 Build 后,Unity 会导出一个浏览器可运行的目录,需要通过本地 HTTP 服务或部署到服务器访问。WebGL 默认有内存限制,过于庞大的场景、纹理和音频会导致浏览器崩溃甚至白屏。建议在 Player Settings > WebGL 中降低纹理压缩等级,控制首包体积,或使用 Addressables 做资源分级加载。

三个平台都在 Build Settings 中操作,但验收标准差异很大。Windows 版本要测试不同分辨率窗口、Alt+F4 退出逻辑和 DPI 缩放;Android 版本要测试触摸输入、屏幕适配和后端生命周期;WebGL 版本要测试浏览器加载进度、包体大小和内存占用。如果项目用了手柄或新 Input System,还需要在键盘、触摸屏、手柄三种输入之间来回切换验证。

构建产物建议放在工程目录之外的 Build 文件夹,不要混入 Assets,否则版本库体积会快速膨胀。Unity 项目由大量文件和 meta 文件组成,多人协作时场景文件容易冲突,务必配合 Git 等版本控制工具管理,并提交 meta 文件。

8. 常见问题与排查思路

入门阶段会遇到的问题高度集中,下面是一个排查表,基本覆盖了上述内容的常见失败场景。

问题现象可能原因排查方式解决方案
角色按下方向键不动输入模块未启用、脚本没挂载查看 Console 是否有报错,确认 Input Handling检查脚本挂载和 Input Manager 设置
角色抖动明显直接改 Transform 与刚体冲突检查角色是否带 Rigidbody,移动代码位置改用 velocity 控制,开启 Interpolate
角色穿墙落地Collider 尺寸过小或位置偏差打开 Physics Debugger 查看碰撞体范围调整 Collider 中心、半径和高度
OnTriggerEnter 不触发Is Trigger 未勾选或缺少 Rigidbody检查 Collider 属性和物体组件勾选 Is Trigger,给一方添加 Rigidbody
OnCollisionEnter 始终不执行方法名写错或状态不对检查事件方法名和碰撞体状态修正方法名,确认非触发器状态
敌人不追击玩家NavMesh 未烘焙、引用为空查看 Scene 中是否有蓝色导航区域重新烘焙,拖拽 playerTarget 引用
Android 构建一直失败SDK/NDK/JDK 缺失在 Unity Hub 检查模块安装安装 Android Build Support
WebGL 打开白屏内存超限或资源包过大查看浏览器 Console 报错压缩纹理和音频,减少首包资源
脚本报 CS0246using 命名空间缺失查看错误输出中类型名补充 using UnityEngine 等命名空间

排查问题要讲究顺序,不要一上来就改代码。先看 Console 有没有红色错误;没有报错就看 Inspector 中的引用是否完整;再不行就用 Debug.Log 打印关键变量,确认逻辑执行到哪一步中断。这个流程比盲目搜索错误信息可靠得多。

9. 最佳实践与工程建议

入门实战到这里接近尾声,最后说几点对未来开发真正有帮助的经验。

第一,脚本职责要单一。角色控制脚本只负责输入和移动,AI 脚本只负责寻路行为,拾取脚本只处理收集事件。不要在一个几百行的 Update 里把移动、射击、血条、金币全写了。这样便于调试和复用,后续替换输入方案或 AI 行为时只需改对应脚本,不影响其他模块。

第二,合理使用 RequireComponent。它强制依赖组件,脚本挂载时 Unity 会自动补齐所需组件,减少“组件缺失导致空引用”的低级错误。PlayerMovement 已经用了 [RequireComponent(typeof(Rigidbody))],后续写其他脚本时可以沿用这个思路。

第三,善用 Tag 和 Layer。角色、敌人、道具尽量使用独立 Tag 或 Layer,而不要靠对象名判断。对象名在运行时可能被修改,而 Tag 和 Layer 是稳定属性。CompareTag 比直接比较 name 更安全,性能也更可控。

第四,控制物理物体的数量。不要在场景中放置大量实时刚体。如果要模拟碎片、爆炸效果,优先考虑对象池或粒子系统,而不是堆大量真实刚体。大型地图可以拆成多个小块 Collider,减少碰撞检测开销,尤其移动端对此非常敏感。

第五,构建要尽早开始。项目第二天就可以尝试切换到 WebGL 或 Android 做一次构建测试。性能问题和兼容性问题发现得越晚,修改成本越高。移动端显存占用、WebGL 包体大小这类指标,应该从早期就纳入验收标准。

第六,版本管理要规范。Unity 依赖 .meta 文件维护资源映射关系,放入 Git 时不要删除 meta 文件,也不要随意重命名资源,否则场景里的引用会断。团队协作时统一 Unity 版本和目录结构,避免不同版本互相覆盖。

入门阶段最容易产生的错觉是“做完验证 Demo 就算结束”。实际上,把本系列的模块串起来——角色移动、拾取金币、敌人追击、多平台构建——你已经拥有一个 3D 跑图小游戏的雏形。接下来可以继续学习 Animator 动画系统、UGUI 界面、粒子特效、对象池、行为树等进阶内容。无论学什么,坚持“先理解协作关系,再动手写代码”的习惯,踩坑数量会明显减少。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/7 13:14:58

2G内存跑通hindsight:AI助理长期记忆实测与避坑指南

上周翻出一台吃灰两年的2G内存小主机&#xff0c;本打算让它当AI助理的长期记忆仓库&#xff0c;结果聊过的事转头就忘&#xff0c;十分钟前说“我喜欢喝冰美式”&#xff0c;换个话题再问就跟失忆一样。后来看到hindsight这个开源项目&#xff0c;号称能给AI助理装上“海马体”…

作者头像 李华
网站建设 2026/10/7 13:14:44

微信小程序购物商城带Java后端:前后端分离实战骨架与避坑指南

简介&#xff1a;这是一套面向计算机专业学生与Java后端开发初学者的微信小程序购物商城完整项目&#xff0c;适合作为课程设计、毕业设计或技能实训的参考方案。项目采用微信小程序前端搭配Java后端&#xff0c;实现商品分类与关键字检索、购物车增减数量、订单提交与收货地址…

作者头像 李华
网站建设 2026/10/7 13:14:44

基于Python的深度学习与计算机视觉课程设计:新冠肺炎X光片预测实战

简介&#xff1a;这份资源是面向计算机相关专业学生与初学者的深度学习与计算机视觉课程设计项目&#xff0c;以Python实现新冠肺炎预测为核心任务&#xff0c;适合人工智能、通信工程、自动化等方向的学生用于课设、毕设、作业或项目立项演示。压缩包共9个文件&#xff0c;约7…

作者头像 李华
网站建设 2026/10/7 13:14:43

Unity炮弹发射全攻略:Rigidbody刚体、瞄准与对象池详解

这次我们来看一个非常具体的问题&#xff1a;在 Unity 里做一颗炮弹&#xff0c;点一下鼠标把它打出去。很多开发者会在搜索里带上“蓝图”&#xff0c;这里必须先纠正一个概念——Unity 没有 Unreal Engine 那种“蓝图&#xff08;Blueprint&#xff09;”可视化脚本系统。如果…

作者头像 李华
网站建设 2026/10/7 13:14:40

嘉立创2026免费打样攻略:4种优惠券领取与使用全解析

嘉立创免费打样&#xff0c;核心就一句话&#xff1a;规则看懂&#xff0c;分币不花。做了七八年PCB&#xff0c;从大学电赛一直打到工作后的产品打样&#xff0c;我的习惯是能薅免费的一定不花钱。嘉立创的免费打样力度确实大&#xff0c;但很多人领了券下单却发现金额对不上、…

作者头像 李华
网站建设 2026/10/7 13:13:08

SOT-23与SOD-523丝印识别指南:二极管、三极管、MOS管速查手册

修板子的时候最烦什么&#xff1f;不是焊盘脱落&#xff0c;不是芯片烧穿&#xff0c;而是面对一个三只脚的小黑点&#xff0c;上面只有一行两三个字符的丝印。SOT-23还好说&#xff0c;好歹还能拿放大镜看个大概&#xff0c;SOD-523这种比芝麻粒大不了多少的封装&#xff0c;丝…

作者头像 李华