本篇核心知识点:场景雾效、项目自定义鼠标光标、开场镜头推进动画、UI 黑白渐变过渡、流光标题文字、任意按键登录弹窗、角色选择场景、TXT 配置表动态生成角色、上下切换角色、本地 PlayerPrefs 持久化、鼠标地面点击寻路、人物旋转锁轴、角色移动动画、代码封装规范、枚举状态管理、图层常量统一管理
一、场景环境基础设置(雾效、天空盒、自定义鼠标)
1 概念
Unity 环境组件快速美化游戏场景,同时修改项目打包后鼠标指针样式,区分编辑器默认光标与游戏内专属光标,提升游戏沉浸感。
2 特性 / 规则
-
Window→Rendering 环境面板勾选 Fog 开启全局雾效,可调整雾浓度、颜色营造朦胧氛围感;
-
天空盒直接替换场景远景背景,不同素材实现晴空、黄昏等场景风格;
-
File→Player Settings 设置 Default Cursor,图片导入为光标素材,打包运行自动替换鼠标;
-
美术场景模型、环境贴图由美工输出,程序仅做参数调试。
3 语法 & 代码片段
无运行代码,全部为编辑器面板配置操作
4 相关知识点对比
默认系统鼠标 VS 游戏自定义光标
默认光标:系统原生样式,割裂游戏美术风格; 自定义光标:和游戏画风统一,提升沉浸式体验。
5 模块拓展
根据场景氛围动态开关雾效,夜晚场景加大雾浓度。
二、开场镜头推进动画(缓动移动)
1 概念
游戏启动时主相机从远处缓慢向前移动至主角初始位置,搭配全屏黑白遮罩渐变、标题文字淡入,制作游戏开篇过场动画。
2 特性 / 规则
-
Update 持续向目标位置插值移动相机,使用 Vector3.Lerp 平滑过渡;
-
设置移动速度控制推进快慢,起始 Z 坐标远离场景,终点对齐玩家出生点位;
-
相机移动逻辑独立脚本挂载 MainCamera,不与其他业务耦合。
3 语法 & 代码片段
public float moveSpeed;
public Vector3 targetPos;
void Update(){
transform.position = Vector3.Lerp(transform.position, targetPos, moveSpeed * Time.deltaTime);
}
4 相关知识点对比
直接平移 Translate VS Lerp 缓动推进
Translate 匀速直线,画面生硬; Lerp 插值由快变慢,镜头推拉影视化效果更自然。
5 模块拓展
镜头推进完成后自动销毁动画脚本,节省每帧运算开销。
三、UI 全屏黑白遮罩渐变过渡
1 概念全屏白色 Image 遮罩跟随镜头推进同步降低透明度,实现画面从纯白逐步清晰的开场过渡效果。
2 特性 / 规则
-
Image 组件铺满整个 Canvas,射线检测关闭,仅做视觉渲染;
-
修改 Color.a 透明度实现淡入淡出,Mathf.Abs 判断渐变完成阈值;
-
渐变逻辑封装独立通用方法,后续弹窗、场景切换可复用。
3 语法 & 代码片段
public Image fadeImg;
public float fadeSpeed;
void Update(){
Color nowColor = fadeImg.color;
nowColor.a = Mathf.Lerp(nowColor.a, 0, fadeSpeed * Time.deltaTime);
fadeImg.color = nowColor;
if(Mathf.Abs(nowColor.a - 0) < 0.01f)
{
enabled = false;
}
}
4 相关知识点对比
逐帧直接赋值 Alpha VS Lerp 平滑渐变
直接赋值:透明度突变,过渡生硬; Lerp 插值:渐变流畅柔和,影视开场标准做法。
5 模块拓展
封装通用渐变工具类,支持渐显、渐隐双向调用。
四、流光闪烁标题文字 + 文本基础设置
1 概念
Text 文本通过 Mathf.PingPong 循环插值颜色,实现红蓝交替流光闪烁效果,搭配 Outline 描边增强文字立体感。
2 特性 / 规则
-
Mathf.PingPong 自动往返 0-1 区间,搭配 Color.Lerp 循环切换两种颜色;
-
Outline 描边组件给文字增加外轮廓,提升深色背景下辨识度;
-
文本层级低于遮罩,保证开场时被白图遮挡。
3 语法 & 代码片段
public Text titleTxt;
void Update(){
float t = Mathf.PingPong(Time.time, 1f);
titleTxt.color = Color.Lerp(Color.red, Color.blue, t);
}
4 相关知识点对比
PingPong 自动循环 VS 计时器手动折返
PingPong 内置往返逻辑,代码极简; 手动计时器需要正负标记,冗余代码更多。
5 模块拓展
给登录按钮、弹窗标题统一添加流光闪烁动效。
五、任意按键呼出登录注册弹窗
1 概念
开场动画结束后,检测玩家任意键盘输入,一次性弹出账号密码输入框与登录、注册按钮,添加标记防止重复触发弹窗。
2 特性 / 规则
-
全局 bool 标记 isPop 避免多次按键重复生成弹窗;
-
Input.anyKeyDown 检测任意按键按下,无需单独监听 A/D/W 等单键;
-
InputField 输入框设置 ContentType 为 Password 隐藏明文密码。
3 语法 & 代码片段
public GameObject loginPanel;
private bool isPop = false;
void Update(){
if(Input.anyKeyDown && !isPop){
loginPanel.SetActive(true);
isPop = true;
}
}
4 相关知识点对比
单独监听按键 VS anyKey 全局检测
单键监听需要写多条 Input 判断,拓展麻烦; anyKey 任意按键均可触发,玩家操作门槛更低。
5 模块拓展
弹窗弹出后关闭镜头动画脚本,减少性能消耗。
六、场景跳转与前后端登录联动
1 概念
登录按钮绑定回调,校验账号密码后通过 SceneManager 加载角色选择场景,对接之前 Socket 服务端完成账号注册、登录数据校验。
2 特性 / 规则
-
场景必须在 Build Settings 添加索引才能正常跳转;
-
登录成功跳转选角,账号不存在 / 密码错误弹窗文字提示;
-
前后端 CS/SC 协议收发账号密码,数据库校验玩家信息。
3 语法 & 代码片段
using UnityEngine.SceneManagement;
public void LoginBtnClick(){
// 发送登录协议至服务端
NetManager.Instance.SendLogin(userName, pwd, LoginCallBack);
}
void LoginCallBack(LoginResult res){
if(res == LoginResult.Success)
SceneManager.LoadScene("RoleSelect");
}
4 相关知识点对比
本地假校验 VS 服务端数据库校验
本地校验无安全保障,可篡改数据作弊; 服务查表统一校验,杜绝本地修改数据外挂。
5 模块拓展
注册按钮新增账号重复判断提示。
七、角色选择场景 TXT 配置表动态生成模型
1 概念
外部 TXT 文本存储所有角色模型资源路径,游戏运行读取文本,拆分字符串批量实例化角色预制,无需手动在编辑器摆放模型。
2 特性 / 规则
-
TXT 内用逗号分隔每条角色配置,一行对应一个角色资源路径;
-
Resources.Load 根据文本路径动态加载模型;
-
新增角色仅修改配置文件,无需改动生成代码。
3 语法 & 代码片段
// 读取TXT配置
TextAsset txt = Resources.Load<TextAsset>("PlayerConfig");
string[] allRole = txt.text.Split('\n');
foreach(string path in allRole){
GameObject rolePrefab = Resources.Load<GameObject>(path.Trim());
Instantiate(rolePrefab, transform);
}
4 相关知识点对比
编辑器手动摆放角色 VS 配置动态生成
手动摆放:新增角色必须手动拖入,项目迭代繁琐; TXT 配置:美术新增模型仅修改文本,程序零改动。
5 模块拓展
替换为 JSON 配置表,支持角色名称、职业、血量多字段存储。
八、上下按钮切换选中角色
1 概念
整型索引记录当前选中角色,点击上 / 下按钮增减索引,边界取模循环,隐藏非选中模型,仅展示当前角色。
2 特性 / 规则
-
索引自增自减后对角色总数取模,实现首尾循环切换;
-
遍历所有角色物体,索引匹配显示,其余全部隐藏;
-
按钮点击逻辑与角色数据完全解耦。
3 语法 & 代码片段
private int selectIndex = 0;
private List<GameObject> allRoles;
// 下一个角色
public void NextRole(){
selectIndex = (selectIndex + 1) % allRoles.Count;
RefreshRoleShow();
}
void RefreshRoleShow(){
for(int i = 0; i < allRoles.Count; i++){
allRoles[i].SetActive(i == selectIndex);
}
}
4 相关知识点对比
if 边界判断 VS 取模循环
if 判断需要单独处理 0 与最大值边界,代码冗长; 取模运算自动循环,一行代码处理首尾切换。
5 模块拓展
选中角色高亮边框特效,区分未选中模型。
九、PlayerPrefs 本地持久化存储
1 概念
Unity 自带注册表持久化工具,存储玩家选中角色、昵称,切换场景、重启游戏数据不丢失。
2 特性 / 规则
-
存储位置:Windows 注册表 CurrentUser→Software→项目名;
-
仅支持 int、float、string 三种基础数据类型;
-
角色索引、玩家昵称在确认按钮写入,主场景读取加载。
3 语法 & 代码片段
// 存储数据
PlayerPrefs.SetInt("RoleIndex", selectIndex);
PlayerPrefs.SetString("PlayerName", inputName.text);
PlayerPrefs.Save();
// 读取数据
int saveIndex = PlayerPrefs.GetInt("RoleIndex", 0);
string saveName = PlayerPrefs.GetInt("Default");
4 相关知识点对比
PlayerPrefs 注册表 VS 本地 TXT 文件
PlayerPrefs 引擎原生,无需 IO 读写代码,操作极简; TXT 文件可自由编辑,易被玩家篡改作弊。
5 模块拓展
玩家金币、等级数据本地缓存。
十、鼠标地面点击寻路移动
1 概念
鼠标左键发射物理射线检测地面标签,获取点击坐标,角色持续向目标点位移动,配套点击地面圆圈特效。
2 特性 / 规则
-
统一常量字符串存储地面标签,避免代码硬编码字符串出错;
-
射线命中后实例点击特效,特效 Y 轴微量抬高防止模型穿插抖动;
-
Vector3.Lerp 匀速向目标点位移动,距离小于阈值停止行走。
3 语法 & 代码片段
public Transform clickEffect;
public float moveSpeed;
private Vector3 targetPos;
void Update(){
if(Input.GetMouseButtonDown(0)){
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if(Physics.Raycast(ray,out RaycastHit hit)){
if(hit.collider.tag == "Ground"){
Vector effectPos = hit.point;
effectPos.y += 0.1f;
Instantiate(clickEffect, effectPos, Quaternion.identity);
targetPos = hit.point;
}
}
}
float dis = Vector3.Distance(transform.position, targetPos);
if(dis > 0.3f){
transform.position = Vector3.Lerp(transform.position, targetPos, moveSpeed * Time.deltaTime);
}
}
4 相关知识点对比
Translate 持续移动 VS Lerp 插值移动
Translate 不受距离控制,会穿过目标点位; Lerp 自动靠近停止,移动手感平滑自然。
5 模块拓展
增加寻路 NavMesh 避开障碍物。
十一、角色朝向 Y 轴锁轴处理
1 概念
角色看向点击点位时,仅修改 Y 轴旋转,X、Z 轴固定归零,防止人物倾斜倒地。
2 特性 / 规则
-
提取目标点位 X、Z,角色自身 Y 值不变构建纯水平面目标;
-
transform.LookAt 锁定水平朝向,重置 X、Z 旋转角度。
3 语法 & 代码片段
Vector3 lookTarget = new Vector3(targetPos.x, transform.position.y, targetPos.z);
transform.LookAt(lookTarget);
4 相关知识点对比
完整三维 LookAt VS 水平面锁轴 LookAt
完整 LookAt 会跟随地面高低倾斜人物; 锁轴仅水平转向,人物始终直立正常。
5 模块拓展
移动过程平滑旋转,不瞬间转头。
十二、角色行走 / 待机枚举动画切换
1 概念
枚举区分 Idle 待机、Move 行走两种角色状态,根据人物与目标距离自动切换 Animation 动画。
2 特性 / 规则
-
枚举统一管理角色状态,替代硬编码数字;
-
距离大于阈值播放行走动画,靠近切换待机;
-
动画组件挂载角色本体,直接控制 Clip 播放。
3 语法 & 代码片段
public enum PlayerState{
Idle,
Move
}
private PlayerState curState;
public Animation anim;
void RefreshAnim(){
if(Vector3.Distance(transform.position, targetPos) > 0.3f)
curState = PlayerState.Move;
else
curState = PlayerState.Idle;
if(curState == PlayerState.Move)
anim.Play("Walk");
else
anim.Play("Idle");
}
4 相关知识点对比
数字标记状态 VS 枚举状态
数字 0/1 无语义,阅读困难易传参错误; 枚举字面量清晰,编译校验错误。
5 模块拓展
新增奔跑、攻击、受伤多状态动画。
十三、代码封装与开发规范
1 概念
项目开发统一封装标准,私有变量使用属性只读暴露、硬编码字符串提取常量、功能单一脚本拆分,降低维护成本。
2 特性 / 规则
-
运行数据变量设为 private,通过 get 只读属性外部访问,防止随意篡改;
-
标签、路径、数值常量提取类头部统一管理;
-
单一功能独立脚本,动画、移动、UI 逻辑分开不堆砌;
-
重复渐变、寻路逻辑封装通用方法复用。
3 语法 & 代码片段
// 只读属性示例
private Vector3 _targetPos;
public Vector3 TargetPos{
get { return _targetPos; }
}
// 常量统一
private const string GroundTag = "Ground";
4 相关知识点对比
公开字段直接访问 VS 私有 + 只读属性
public 字段外部可随意修改,破坏数据逻辑; 私有变量仅内部修改,外部只读,程序更稳定。
5 模块拓展
项目全局常量静态类,统一存储所有标签、路径、数值。
综合拓展
1 RPG 项目初期开发流程
场景环境配置→开场镜头 + UI 过渡动画→登录前后端校验→角色选择 TXT 配置动态生成→本地存储角色昵称→主场景鼠标点击寻路 + 动画切换;
2 高频 Bug 排查清单
人物倾斜倒地:LookAt 未锁定 Y 轴;
点击特效地面抖动:特效 Y 未抬高;
TXT 角色不加载:资源路径换行 / 空格未 Trim;
切换角色模型重叠:未做隐藏逻辑;
登录无响应:服务端账号校验协议不匹配;
数据重启丢失:未调用 PlayerPrefs.Save;
3 考点
TXT 配置动态加载、PlayerPrefs 持久化、鼠标射线地面寻路、人物锁轴旋转、枚举状态动画、Lerp 缓动动画、前后端登录数据交互;
4 进阶拓展学习方向
NavMesh 自动寻路、Protobuf 配置替代 TXT、TMP 高性能文本、UGUI 背包系统、多渠道登录、怪物 AI;