【Unity实战】手戳一个自定义角色换装系统——2d3d通用

文章目录

  • 每篇一句
  • 前言
  • 素材
  • 开始
    • 切换头型
    • 添加更改颜色
    • 随机控制头型和颜色
    • 新增眼睛
    • 同样的方法配置人物的其他部位
    • 设置相同颜色部位
    • 全部部位随机
    • 绘制UI并添加点击事件
    • 通过代码控制点击事件
    • 添加颜色修改的事件
    • 其他部位效果UI切换
    • 添加随机按钮
    • 保存角色变更数据
    • 跳转场景显示角色数据
  • 源码
  • 完结

每篇一句

你进步的速度,取决于你学习的速度,昨天的我,也跟今天的你一样。

前言

本文我们来手戳一个自定义角色换装系统,它包括基本的人物部位、颜色修改,并跨场景显示修改的人物信息,2d3d通用

最终效果
在这里插入图片描述

素材

链接:https://pan.baidu.com/s/1dubEMMBO-ZSm3gQWPkvmsA?pwd=5zi6
提取码:5zi6

开始

切换头型

新建PositionedSprite脚本,保存图片和位置位置

using UnityEngine;[System.Serializable]
public class PositionedSprite
{public Sprite Sprite; // Sprite对象public Vector3 PositionModifier; // 位置修正器
}

新建CustomizableElement脚本,控制图片切换

using System.Collections.Generic;
using UnityEngine;public class CustomizableElement : MonoBehaviour
{[SerializeField]private SpriteRenderer _spriteRenderer; // Sprite渲染器[SerializeField]private List<PositionedSprite> _spriteOptions; // 可选的Sprite列表[SerializeField]private List<Color> _colorOptions; // 可选的颜色列表[field: SerializeField]public int ColorIndex { get; set; } // 颜色索引[field: SerializeField]public int SpriteIndex { get; private set; } // Sprite索引[ContextMenu(itemName: "下一个图片")]public PositionedSprite NextSprite(){SpriteIndex = Mathf.Min(SpriteIndex + 1, _spriteOptions.Count - 1); // 切换到下一个SpriteUpdateSprite();return _spriteOptions[SpriteIndex];}[ContextMenu(itemName: "上一个图片")]public PositionedSprite PreviousSprite(){SpriteIndex = Mathf.Max(SpriteIndex - 1, 0); // 切换到上一个SpriteUpdateSprite();return _spriteOptions[SpriteIndex];}private void UpdateSprite(){if(_spriteOptions.Count == 0) return;SpriteIndex = Mathf.Clamp(SpriteIndex, 0, _spriteOptions.Count - 1); // 限制Sprite索引在合法范围内var positionedSprite = _spriteOptions[SpriteIndex];_spriteRenderer.sprite = positionedSprite.Sprite; // 更新Spritetransform.localPosition = positionedSprite.PositionModifier; // 更新位置}
}

挂载并配置参数
在这里插入图片描述

效果
在这里插入图片描述

添加更改颜色

[ContextMenu(itemName: "下一个颜色")]
public Color NextColor()
{ColorIndex = Mathf.Min(ColorIndex + 1, _colorOptions.Count - 1); // 切换到下一个颜色UpdateColor();return _colorOptions[ColorIndex];
}[ContextMenu(itemName: "上一个颜色")]
public Color PreviousColor()
{ColorIndex = Mathf.Max(ColorIndex - 1, 0); // 切换到上一个颜色UpdateColor();return _colorOptions[ColorIndex];
}private void UpdateColor()
{if(_colorOptions.Count == 0) return;_spriteRenderer.color = _colorOptions[ColorIndex]; // 更新颜色
}

配置
在这里插入图片描述
效果
在这里插入图片描述

随机控制头型和颜色

[ContextMenu(itemName: "随机化")]
public void Randomize()
{SpriteIndex = Random.Range(0, _spriteOptions.Count); // 随机选择一个Sprite索引ColorIndex = Random.Range(0, _colorOptions.Count); // 随机选择一个颜色索引UpdateSprite();UpdateColor();
}

效果
在这里插入图片描述

新增眼睛

同理,添加眼睛,并配置眼睛的位置
在这里插入图片描述
效果
在这里插入图片描述

同样的方法配置人物的其他部位

效果
在这里插入图片描述

设置相同颜色部位

可能我们不希望所有部位都真的随机变色,比如我希望角色的肤色颜色保持一致
在这里插入图片描述
修改代码

[SerializeField]
private List<SpriteRenderer> _copyColorTo; // 需要拷贝颜色的SpriteRenderer列表// ...private void UpdateColor()
{if(_colorOptions.Count == 0) return;var newColor = _colorOptions[ColorIndex]; // 获取新的颜色_spriteRenderer.color = newColor; // 更新当前SpriteRenderer的颜色// 将颜色拷贝到其他SpriteRenderer_copyColorTo.ForEach(sr => sr.color = newColor);
}

配置
在这里插入图片描述
当我们更新头颜色时,手会同步更新,保持头跟手颜色一样
效果
在这里插入图片描述

全部部位随机

新增CustomizationRandomizer 代码

using UnityEngine;public class CustomizationRandomizer : MonoBehaviour
{[ContextMenu(itemName: "随机全部")]public void Randomize(){var elements = GetComponentsInChildren<CustomizableElement>(); // 获取所有CustomizableElement组件foreach (var element in elements){element.Randomize(); // 调用CustomizableElement的Randomize方法,随机化每个元素}}
}

挂载脚本,效果
在这里插入图片描述

绘制UI并添加点击事件

效果

通过代码控制点击事件

一个个配置按钮事件太麻烦了,我们可以通过脚本来控制

public class UI_CustomizationPicker : MonoBehaviour
{[SerializeField]private CustomizableElement _customizableElement; // 自定义元素对象[SerializeField]private Button _previousSpriteButton;[SerializeField]private Button _nextSpriteButton;[SerializeField]private TMP_Text _spriteId;private void Start(){UpdateSpriteId();// 为按钮添加点击事件_previousSpriteButton.onClick.AddListener(() =>{_customizableElement.PreviousSprite(); // 切换到上一个SpriteUpdateSpriteId(); // 更新Sprite的ID文本});_nextSpriteButton.onClick.AddListener(() =>{_customizableElement.NextSprite(); // 切换到下一个SpriteUpdateSpriteId(); // 更新Sprite的ID文本});}private void UpdateSpriteId(){// 更新Sprite的ID文本_spriteId.SetText(_customizableElement.SpriteIndex.ToString().PadLeft(2, '0'));}
}

配置参数
在这里插入图片描述

效果
在这里插入图片描述

添加颜色修改的事件

修改CustomizableElement获取当前的颜色

public Color CurrentColor => _colorOptions.Count == 0 ? Color.white : _colorOptions[ColorIndex]; //获取当前的颜色

修改UI_CustomizationPicker,添加颜色切换事件

[SerializeField]
private Button _previousColorButton;
[SerializeField]
private Button _nextColorButton;
[SerializeField]
private Image _colorIcon;private void Start()
{// 。。。if(_colorIcon != null){_previousColorButton.onClick.AddListener(() =>{_customizableElement.PreviousColor();UpdateColorIcon();});_nextColorButton.onClick.AddListener(() =>{_customizableElement.NextColor();UpdateColorIcon();});}
}private void UpdateColorIcon()
{_colorIcon.color = _customizableElement.CurrentColor;
}

效果
在这里插入图片描述

其他部位效果UI切换

跟前面一样配置各个部位的切换即可,配置其他部位最终效果
在这里插入图片描述
效果
在这里插入图片描述

添加随机按钮

新增脚本UI_CustomizationUI,定义随机按钮事件

public class UI_CustomizationUI : MonoBehaviour
{private List<UI_CustomizationPicker> _pickers; // 自定义选择器列表void Start(){_pickers = GetComponentsInChildren<UI_CustomizationPicker>().ToList(); // 获取所有自定义选择器组件并转换为列表}// 更新所有选择器的状态public void UpdatePickersState(){_pickers.ForEach(picker =>{picker._customizableElement.Randomize();//随机修改picker.UpdateSpriteId(); // 更新Sprite的ID文本picker.UpdateColorIcon(); // 更新颜色图标});}
}

挂载脚本
在这里插入图片描述

效果
在这里插入图片描述

保存角色变更数据

新增CustomizationType 脚本,定义不同部位类型

using UnityEngine;[CreateAssetMenu]
public class CustomizationType : ScriptableObject
{}

添加各个部位配置
在这里插入图片描述
新增CustomizationData脚本,定义各种数据

using UnityEngine;
using System;[Serializable]
public class CustomizationData
{// 使用情况:指定自定义类型[field:SerializeField]public CustomizationType Type { get; private set; }// 使用情况:指定带位置的精灵[field:SerializeField]public PositionedSprite Sprite { get; private set; }// 使用情况:指定颜色[field:SerializeField]public Color Color { get; private set; }// CustomizationData 类的构造函数public CustomizationData(CustomizationType t, PositionedSprite s, Color c){Type = t;Sprite = s;Color = c;}
}

修改CustomizableElement

[SerializeField]
private CustomizationType _type;public CustomizationData GetCustomizationData(){return new CustomizationData(_type, _spriteOptions[SpriteIndex], _spriteRenderer.color);
}

绑定对应数据
在这里插入图片描述

新增CustomizedCharacter,保存人物各个部位数据

using UnityEngine;
using System.Collections.Generic;[CreateAssetMenu]
public class CustomizedCharacter : ScriptableObject
{// Usage: 包含所有自定义数据的列表[field:SerializeField]public List<CustomizationData> Data { get; private set; }// 收集所有可定制元素的自定义数据public void GatherCustomizationData(){// 查找场景中的所有可定制元素var customizableElements = FindObjectsOfType<CustomizableElement>();// 创建一个新的自定义数据列表Data = new List<CustomizationData>();// 遍历所有可定制元素并添加它们的自定义数据到列表中foreach (var element in customizableElements){Data.Add(element.GetCustomizationData());}}
} 

新增人物配置
在这里插入图片描述

新增CustomizableCharacter

using UnityEngine;public class CustomizableCharacter : MonoBehaviour
{[SerializeField]private CustomizedCharacter _character;// Usage: 在编辑器中的上下文菜单中添加 "Randomize All" 选项[ContextMenu(itemName: "Randomize All")]// Usage: 随机化所有可定制元素的外观public void Randomize(){// 获取所有子物体中的 CustomizableElement 组件数组var elements = GetComponentsInChildren<CustomizableElement>();// 遍历每个可定制元素,随机化其外观foreach (var element in elements){element.Randomize();}}// Usage: 存储定制信息public void StoreCustomizationInformation(){// 获取所有子物体中的 CustomizableElement 组件数组var elements = GetComponentsInChildren<CustomizableElement>();// 清空已有的定制数据_character.Data.Clear();// 遍历每个可定制元素,获取其定制数据并添加到角色的数据列表中foreach (var element in elements){_character.Data.Add(element.GetCustomizationData());}}
}

挂载脚本,配置数据
在这里插入图片描述
新增按钮用于跳转和保持角色数据
在这里插入图片描述
效果,数据被保存在了Player里在这里插入图片描述

跳转场景显示角色数据

新增CustomizedCharacterElement脚本,用来渲染角色各个部位的图片和颜色

using UnityEngine;
using System.Linq;public class CustomizedCharacterElement : MonoBehaviour
{// Usage: 指定该元素的自定义类型[field:SerializeField]public CustomizationType Type { get; private set; }// Usage: 指定所属的自定义角色[SerializeField]private CustomizedCharacter _character;private SpriteRenderer _spriteRenderer;// Start 方法在对象实例化时调用private void Start(){// 获取 SpriteRenderer 组件_spriteRenderer = GetComponent<SpriteRenderer>();// 查找自定义角色中指定类型的自定义数据var customization = _character.Data.FirstOrDefault(d => d.Type == Type);// 如果找不到匹配的自定义数据,则返回if (customization == null){return;}// 应用自定义数据中的颜色和精灵到元素上_spriteRenderer.color = customization.Color;_spriteRenderer.sprite = customization.Sprite.Sprite;// 应用自定义数据中的位置修正器到元素上transform.localPosition = customization.Sprite.PositionModifier;}
}

新建场景,挂载脚本,添加配置角色属性
在这里插入图片描述
修改CustomizableCharacter脚本,添加跳转场景方法

//跳转场景
SceneManager.LoadScene("Game");

效果
在这里插入图片描述

源码

为了防止大家变懒,源码就不提供了,大家直接可以照着文章思路进行学习

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。点赞越多,更新越快哦!当然,如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

好了,我是向宇,https://xiangyu.blog.csdn.net

一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/120960.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python-自动化绘制股票价格通道线

常规方案 通过将高点/低点与其 2 个或 3 个相邻点进行比较来检测枢轴点,并检查它是否是其中的最高/最低点。对所有枢轴点进行线性回归以获得上方和下方趋势线。价格离开通道后建仓。通过这样做,我们得到如下所示的价格通道。我认为我们可以利用给定的数据取得更好的结果。

【算法|动态规划No30】leetcode5. 最长回文子串

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【手撕算法系列专栏】【LeetCode】 &#x1f354;本专栏旨在提高自己算法能力的同时&#xff0c;记录一下自己的学习过程&#xff0c;希望…

C语言之预处理

目录 前言 宏定义define的用法 文件包含include的用法 条件编译的用法 其他预处理命令 练习题 练习一 练习二 练习三 前言 预处理命令可以改变程序设计环境&#xff0c;提高编程效率&#xff0c;它们并不是C语言本身的组成部分&#xff0c;不能直接对它们进行编译&am…

redis高可用

文章目录 redis高可用概述哨兵模式原理配置流程使用缺点 cluster集群原理特征流程缺点故障转移故障检测故障转移 集群配置和管理主要命令搭建集群创建集群查看集群配置信息测试集群主从切换扩容缩容 redis高可用概述 1、高可用是分布式的概念。 Redis的高可用性是指在Redis集群…

springsecurity学习笔记-未完

目录 前言 一、概念 1.什么是springsecurity 2.对比shiro 二、开始项目 1.建立一个空项目&#xff0c;建立module&#xff0c;引入相关依赖 2.启动项目&#xff0c;访问项目 3.自定义密码 总结 前言 记录一下学习springsecurity的过程 开发环境&#xff1a;IDEA 一、概念 1.…

解决提交到App Store时的ITMS-90478和ITMS-90062错误

解决提交到App Store时的ITMS-90478和ITMS-90062错误 目录 引言 正文 1. 什么是ITMS-90478和ITMS-90062错误&#xff1f; 2. 解决方法 2.1 确定当前的版本号和构建号 2.2 递增版本号和构建号 2.3 再次尝试提交应用 总结 参考资料 错误记录 摘要&#xff1a;本文为iOS…

鼎鑫鸿鄴引入“能源互联网+”理念 打造共赢

近年来&#xff0c;随着全球能源消耗的不断增长和环境问题的日益突出&#xff0c;清洁能源转型成为全球共同关注的话题。中国作为全球最大的能源消费国&#xff0c;也在积极推动能源结构的优化和清洁能源的发展。鼎鑫鸿鄴新能源科技有限公司在推动清洁能源转型方面制定了一系列…

北太天元安装教程 及使用方法

北太天元是面向科学计算与工程计算的国产通用型科学计算软件。提供科学计算、可视化、交互式程序设计&#xff0c;具备丰富的底层数学函数库&#xff0c;支持数值计算、数据分析、数据可视化、数据优化、算法开发等工作&#xff0c;并通过SDK与API接口&#xff0c;扩展支持各类…

Vite介绍及实现原理

Vite介绍及实现原理 一、Vite简介1.1、什么是Vite1.2 、Vite的主要特性1.3、 为什么要使用Vite 二、Vite的实现原理2.1、依赖处理2.2、静态资源加载2.3、vue文件缓存2.4、 js/ts处理 三、热更新原理四、vite基本使用4.1、安装4.2、搭建项目 一、Vite简介 1.1、什么是Vite Vite…

计算机网络——理论知识总结(上)

开新番&#xff0c;因为博主备考的学校计网只考察1/6的分值&#xff0c;而且定位偏向于送分题&#xff0c;因此在备考时并没有很高强度的复习。本帖基于王道考研的教辅总结归纳&#xff0c;虽然是408的教材&#xff0c;但忽略其中有难度的部分&#xff0c;如计算题、画图题等&a…

如何通过员工工时管理降低企业成本?

作为当今快节奏商业环境的领导者或管理者&#xff0c;掌握员工的工作时间对于控制企业成本和确保每个人都各尽其责至关重要。 员工工时表软件就是这样一款工时跟踪管理解决方案&#xff1a;数字化的工时表有助于保护企业的财务不会被无节制的开支冲垮。然而&#xff0c;引入此…

Spark SQL概述与基本操作

目录 一、Spark SQL概述 &#xff08;1&#xff09;概念 &#xff08;2&#xff09;特点 &#xff08;3&#xff09;Spark SQL与Hive异同 &#xff08;4&#xff09;Spark的数据抽象 二、Spark Session对象执行环境构建 (1)Spark Session对象 &#xff08;2&#xff09;代码演…

Flink on yarn 加载失败plugins失效问题解决

Flink on yarn 加载失败plugins失效问题解决 flink版本&#xff1a;1.13.6 1. 问题 flink 任务运行在yarn集群,plugins加载失效,导致通过扩展资源获取任务参数失效 2. 问题定位 yarn容器的jar包及插件信息,jar包是正常上传 源码定位 加载plugins入口&#xff0c;TaskMana…

TCP三次握手具体过程

四次挥手 1&#xff09;客户端进程发出连接释放报文&#xff0c;并且停止发送数据。释放数据报文首部&#xff0c;FIN1&#xff0c;其序列号为sequ&#xff08;等于前已经传送过来的数据的最后一个字节的序号加1)&#xff0c;此时&#xff0c;客户端进入FIN_WAIT_1&#xff08…

AI新能量!FortiGate NGFW面向数据中心全面集成FortiGuard AI 安全服务

企业IT技术正在以惊人的速度发展&#xff0c;转型最大的领域之一是下一代防火墙&#xff08;NGFW&#xff09;市场。如今&#xff0c;混合云、多云、边缘等多种基础设施形态共存&#xff0c;已经成为大部分企业的常态&#xff0c;不断扩张的攻击面需要不同形态防火墙的安全防护…

若依ruoyi-nbcio如何做一个仿钉钉流程设计器的思考

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 看到有些流程图采用仿钉钉的流程设计&#xff0c;比如下面界面&#xff1a; 这种方式虽然简单&#xff0c…

计算机网络文章荟萃

脑残式网络编程入门(二)&#xff1a;我们在读写Socket时&#xff0c;究竟在读写什么&#xff1f;-网络编程/专项技术区 - 即时通讯开发者社区! 1.什么是 socket - 掘金2.socket 的实现原理 - 掘金本文讲述了 socket 在 linux 操作系统下的数据结构&#xff0c;以及阻塞 IO 利用…

檢測項目簡體字

某些項目可能要求代碼中不允許使用簡體字 安裝stcheck檢查 yarn add stcheck --dev在項目根目錄創建 st.config.json 文件 {"patterns": ["./**/*.(ts|js|tsx|jsx|vue|html)","!**/node_modules/**","!.git/**"],"gitignore&q…

Express框架开发接口之登录与注册API

我们利用nodeexpressmysql开发接口&#xff0c;对数据库数据进行简单增、删、查改等操作。 接口是什么&#xff1f; 接口是 前后端通信的桥梁 简单理解&#xff1a;一个接口就是 服务中的一个路由规则 &#xff0c;根据请求响应结果 接口的英文单词是 API (Application Progra…

Java工具库——FastJson的40个常用方法

那些想看却没看的书&#xff0c;在心里摆满一个图书馆… 工具库介绍 阿里巴巴的 FastJSON&#xff0c;也被称为 Alibaba FastJSON 或阿里巴巴 JSON&#xff0c;是一个高性能的 Java JSON 处理库&#xff0c;用于在 Java 应用程序中解析和生成 JSON 数据。FastJSON 以其卓越的性…