返回首页DA系统C#IDE文件同步服务屏保 今天是: 2026-05-05    "立夏"  夏季的第一个节气,表示盛夏时节的正式开始

搜索
热搜: linux 技术
Hi~登录注册
查看: 2669|回复: 0

[原创] 【原创】使用NGUI的换装Demo

[复制链接]
发表于 2022-11-4 18:45:17 | 显示全部楼层 |阅读模式
本帖最后由 da11 于 2022-11-10 12:12 编辑

//20221104
//一共使用3个脚本类
//M2NGUIButtonChick.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class M2NGUIButtonChick : MonoBehaviour
{
    /*角色换装demo案例
     *
     * 需求分析:
     *  · 角色选择
     *  · 服装选择
     *  · 武器选择
     *  · 动画选择(动画需要优化,暂时不展示)
     *  
     * 技术分析:
     * · 点击按钮实现切换
     * · 按钮功能分为四类,对应上述需求分析
     * · 不同功能对应不同美术资源
     *
     * 问题:
     * · 如何管理按钮点击(按钮只负责输入,不负责具体业务处理)
     * · 如何组织功能(业务单独处理)
     * · 如何管理美术资源在场景中的使用(资源存放,动态加载)



     *
     * 此脚本是按钮处理脚本,挂在按钮的父级物体上
     *
    */

    //NGUI按钮按下时,自动分配委托方法的脚本
    //挂在UI的父物体上

    //定义主业务脚本类
    private M2NGUIChangecloth_Script centerScript;

    //存放按钮的名字
    private string ButtonName;

    //存放切割后的按钮名字数组
    private string[] ButtonSplitName;

    //存放切割后的按钮功能名称
    private string FunctionName;

    //存放切割后的按钮资源名称
    private string ResourcesName;

    private void Start()
    {
        //获取主脚本类的引用
        centerScript = FindObjectOfType<M2NGUIChangecloth_Script>();

        //transform.childCount 统计子物体数量,相当好用的统计
        for (int i = 0; i < transform.childCount; i++)
        {
            //为每个子物体中的UIButton类中的onClick增加委托方法,委托方法引用OnButtonChick方法。
            //new EventDelegate 是第三阶段的委托讲解,现在只需要使用
            transform.GetChild(i).GetComponent<UIButton>().onClick.Add(new EventDelegate(OnButtonChick));
        }
    }

    //指定按钮按下时执行的方法
    private void OnButtonChick()
    {
        //UIButton.current.name 属性是当前按下的UI名字
        //print("按下的按钮名称是 " + UIButton.current.name);
        ButtonName = UIButton.current.name;

        //字符串的切割
        //Split方法,将字符串中每个分割符(这里分割符指定是空格)分割的子字符串放入string类型的数组中,需要字符串数组类型接收
        ButtonSplitName = ButtonName.Split(' ');

        print("按下的按钮名称是 " + ButtonSplitName[0] +" "+ ButtonSplitName[1]);

        //根据按钮切割后的名字获取按钮功能名称
        FunctionName = ButtonSplitName[0];

        //根据按钮切割后的名字获取按钮资源名称
        ResourcesName = ButtonSplitName[1];

        switch (FunctionName)
        {
            case "Weapons":
                //调用ChangeWeapons方法更换武器
                centerScript.ChangeWeapons(ResourcesName);
                break;
            case "Animation":
                //调用ChangeAnimation方法更换动画
                centerScript.ChangeAnimation(ResourcesName);
                break;
            case "Character":
                //调用ChangeCharacter方法更换人物
                centerScript.ChangeCharacter(ResourcesName);
                break;
            case "Clother":
                //调用ChangeClother方法更换衣服
                centerScript.ChangeClother(ResourcesName);
                break;
        }
    }
}






本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册成为修仙之旅的少年~

x
 楼主| 发表于 2022-11-4 18:46:38 | 显示全部楼层
本帖最后由 da11 于 2022-11-4 18:49 编辑

//M2NGUIChangecloth_Script.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class M2NGUIChangecloth_Script : MonoBehaviour
{
    /*角色换装demo案例
     *
     * 需求分析:
     *  · 角色选择
     *  · 服装选择
     *  · 武器选择
     *  · 动画选择(动画需要优化,暂时不展示)
     *  
     * 技术分析:
     * · 点击按钮实现切换
     * · 按钮功能分为四类,对应上述需求分析
     * · 不同功能对应不同美术资源
     *
     * 问题:
     * · 如何管理按钮点击(按钮只负责输入,不负责具体业务处理)
     * · 如何组织功能(业务单独处理)
     * · 如何管理美术资源在场景中的使用(资源存放,动态加载)
     *
     * 此脚本是主业务处理主脚本,挂在demo准备的原点空物体上(“characterCreation”)
     *
    */

    private M2NGUIResourcesLoad_script ResourcesLoad = new M2NGUIResourcesLoad_script();

    private Object Character;


    private GameObject WeaponTF;

    private Object Weapon;

    private GameObject ClotherTF;

    private Texture Clother;

    private Object Animation;



    private void Start()
    {
        PlayerPrefs.DeleteKey("Character");
        PlayerPrefs.DeleteKey("Weapons");      
    }

    //更换人物方法
    public void ChangeCharacter(string ResourcesName)
    {
        //查询是否有人物存储,有则销毁,因为是更换另一个人物,所以需要销毁
        if (PlayerPrefs.HasKey("Character"))
        {
            Object.Destroy(this.transform.GetChild(0).gameObject);
            //清除人物存储等于初始化人物
            PlayerPrefs.DeleteKey("Character");
            //清除武器存储等于初始化武器
            PlayerPrefs.DeleteKey("Weapons");
        }

        Character = ResourcesLoad.Characterload(ResourcesName);

        Instantiate(Character, this.transform.position, this.transform.rotation, this.transform);

        //生成后存储此人物名称
        PlayerPrefs.SetString("Character", ResourcesName);

    }


    //更换武器方法
    public void ChangeWeapons(string ResourcesName)
    {
        //首先判断有没有人物的存储,有则可以生成武器
        if (PlayerPrefs.HasKey("Character"))
        {
            //查询是否有武器存储,有则销毁,因为是更换另一个武器,所以需要销毁
            if (PlayerPrefs.HasKey("Weapons"))
            {
                Object.Destroy(WeaponTF.transform.GetChild(0).gameObject);
                PlayerPrefs.DeleteKey("Weapons");
            }

            //获取武器物体
            Weapon = ResourcesLoad.Weaponsload(ResourcesName);

            WeaponTF = GameObject.Find("wphand");

            //生成武器
            Instantiate(Weapon, WeaponTF.transform.position, WeaponTF.transform.rotation, WeaponTF.transform);

            //生成后存储此武器名称
            PlayerPrefs.SetString("Weapons", ResourcesName);
        }
        else
        {
            print("对不起,没有生成人物,所以不能生成武器");
        }

    }

    //更换衣服方法
    public void ChangeClother(string ResourcesName)
    {
        //首先判断有没有人物的存储,有则可以生成衣服
        if (PlayerPrefs.HasKey("Character"))
        {
            Clother = ResourcesLoad.Clotherload(PlayerPrefs.GetString("Character","name"),ResourcesName);

            ClotherTF = GameObject.Find("mon_"+PlayerPrefs.GetString("Character", "name"));

            ClotherTF.GetComponent<Renderer>().material.mainTexture = Clother;

        }
        else
        {
            print("对不起,没有生成人物,所以不能生成衣服");
        }

    }

    //更换动画方法
    public void ChangeAnimation(string ResourcesName)
    {
        //首先需要判断角色是否为空
        //不为空时才播放ResourcesName动画
        if (PlayerPrefs.HasKey("Character"))
        {
            //Animation = ResourcesLoad.Animationload(ResourcesName);
        }
        else
        {
            print("没有人物呢,播放不了动画");
        }
    }




}


回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-4 18:49:17 | 显示全部楼层
//M2NGUIResourcesLoad_script.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class M2NGUIResourcesLoad_script : MonoBehaviour
{
    /*角色换装demo案例
     *
     * 需求分析:
     *  · 角色选择
     *  · 服装选择
     *  · 武器选择
     *  · 动画选择(动画需要优化,暂时不展示)
     *  
     * 技术分析:
     * · 点击按钮实现切换
     * · 按钮功能分为四类,对应上述需求分析
     * · 不同功能对应不同美术资源
     *
     * 问题:
     * · 如何管理按钮点击(按钮只负责输入,不负责具体业务处理)
     * · 如何组织功能(业务单独处理)
     * · 如何管理美术资源在场景中的使用(资源存放,动态加载)
     *
     * 此脚本是资源加载脚本,不挂在任何物体上,当作工具类
     *
    */

    //资源加载类脚本(一般称为工厂类)

    public Object[] AllWeapons;

    public Object[] AllCharacter;

    public Texture[] AllClother;

    public Object[] AllAnimation;

    /// <summary>
    /// 加载武器方法
    /// </summary>
    /// <param name="resourcesName">资源名称</param>
    /// <returns></returns>
    public Object Weaponsload(string resourcesName)
    {
        AllWeapons = Resources.LoadAll("Weapons/");

        for (int i = 0; i < AllWeapons.Length; i++)
        {
            if (AllWeapons.name == "wp_"+resourcesName)
            {
                return AllWeapons;
            }
        }
        return null;
    }

    /// <summary>
    /// 加载人物方法
    /// </summary>
    /// <param name="resourcesName">资源名称</param>
    public Object Characterload(string resourcesName)
    {
        AllCharacter = Resources.LoadAll("Prefabs/");

        for (int i = 0; i < AllCharacter.Length; i++)
        {
            if (AllCharacter.name == "mon_" + resourcesName)
            {
                return AllCharacter;
            }
        }


        print(AllCharacter.Length);

        return null;
    }

    /// <summary>
    /// 加载衣服方法
    /// </summary>
    /// <param name="resourcesName">资源名称</param>
    public Texture Clotherload(string manName,string resourcesName)
    {

        AllClother = Resources.LoadAll<Texture>("Clother/");

        for (int i = 0; i < AllClother.Length; i++)
        {
            if (AllClother.name == "mon_"+manName +"_"+ resourcesName)
            {
                return AllClother;
            }
        }

        return null;
    }

    public Object Animationload(string resourcesName)
    {
        AllAnimation = Resources.LoadAll<Object>("");
        return null;

    }
}



回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-4 18:54:42 | 显示全部楼层
最后演示Demo效果:


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册成为修仙之旅的少年~

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-9 17:33:46 | 显示全部楼层
//更新代码-M2NGUIChangecloth_Script.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class M2NGUIChangecloth_Script : MonoBehaviour
{
    /*角色换装demo案例
     *
     * 需求分析:
     *  · 角色选择
     *  · 服装选择
     *  · 武器选择
     *  · 动画选择
     *  
     * 技术分析:
     * · 点击按钮实现切换
     * · 按钮功能分为四类,对应上述需求分析
     * · 不同功能对应不同美术资源
     *
     * 问题:
     * · 如何管理按钮点击(按钮只负责输入,不负责具体业务处理)
     * · 如何组织功能(业务单独处理)
     * · 如何管理美术资源在场景中的使用(资源存放,动态加载)
     *
     * 此脚本是主业务处理主脚本,挂在demo准备的原点空物体上(“characterCreation”)
     *
    */

    private M2NGUIResourcesLoad_script ResourcesLoad = new M2NGUIResourcesLoad_script();

    private Object Character;

    private GameObject CharacterGameObj;

    private Transform WeaponTF;

    private Object Weapon;

    //递归返回的Transform组件
    private Transform childTF;

    private GameObject ClotherTF;

    private Texture Clother;

    private Object Animation;



    private void Start()
    {
        PlayerPrefs.DeleteKey("Character");
        PlayerPrefs.DeleteKey("Weapons");
        childTF = null;
    }

    //更换人物方法
    public void ChangeCharacter(string ResourcesName)
    {
        //查询是否有人物存储,有则销毁,因为是更换另一个人物,所以需要销毁
        if (PlayerPrefs.HasKey("Character"))
        {
            Object.Destroy(this.transform.GetChild(0).gameObject);
            //清除人物存储等于初始化人物
            PlayerPrefs.DeleteKey("Character");
            //清除武器存储等于初始化武器
            PlayerPrefs.DeleteKey("Weapons");
        }

        Character = ResourcesLoad.Characterload(ResourcesName);

        CharacterGameObj = (GameObject)Instantiate(Character, this.transform.position, this.transform.rotation, this.transform);

        //生成后存储此人物名称
        PlayerPrefs.SetString("Character", ResourcesName);

    }


    //更换武器方法
    public void ChangeWeapons(string ResourcesName)
    {
        //首先判断有没有人物的存储,有则可以生成武器
        if (PlayerPrefs.HasKey("Character"))
        {
            //查询是否有武器存储,有则销毁,因为是更换另一个武器,所以需要销毁
            if (PlayerPrefs.HasKey("Weapons"))
            {
                Object.Destroy(WeaponTF.transform.GetChild(0).gameObject);
                PlayerPrefs.DeleteKey("Weapons");
            }

            //获取武器物体
            Weapon = ResourcesLoad.Weaponsload(ResourcesName);

            //使用递归查找武器挂载点位置,比直接GameObject.Find性能要好
            //WeaponTF = GameObject.Find("wphand");
            WeaponTF = GetNameFindGameObject(CharacterGameObj.transform, "wphand");

            //生成武器
            Instantiate(Weapon, WeaponTF.transform.position, WeaponTF.transform.rotation, WeaponTF.transform);

            //生成后存储此武器名称
            PlayerPrefs.SetString("Weapons", ResourcesName);
        }
        else
        {
            print("对不起,没有生成人物,所以不能生成武器");
        }

    }

    //更换衣服方法
    public void ChangeClother(string ResourcesName)
    {
        //首先判断有没有人物的存储,有则可以生成衣服
        if (PlayerPrefs.HasKey("Character"))
        {
            Clother = ResourcesLoad.Clotherload(PlayerPrefs.GetString("Character","name"),ResourcesName);

            ClotherTF = GameObject.Find("mon_"+PlayerPrefs.GetString("Character", "name"));

            ClotherTF.GetComponent<Renderer>().material.mainTexture = Clother;

        }
        else
        {
            print("对不起,没有生成人物,所以不能生成衣服");
        }

    }

    //更换动画方法
    public void ChangeAnimation(string ResourcesName)
    {
        //首先需要判断角色是否为空
        //不为空时才播放ResourcesName动画
        if (PlayerPrefs.HasKey("Character"))
        {
            //播放首选动画,调取人物的Animation组件
            CharacterGameObj.GetComponent<Animation>().CrossFade(ResourcesName);
        }
        else
        {
            print("没有人物呢,播放不了动画");
        }
    }



    /// <summary>
    /// 使用递归获取子物体
    /// </summary>
    /// <param name="GOTF">父物体的Transform组件</param>
    /// <param name="name">需要查找的子物体名称</param>
    /// <returns></returns>
    public Transform GetNameFindGameObject(Transform GOTF, string name)
    {  
        for (int i = 0; i < GOTF.childCount; i++)
        {
            //调试行
            //print(GOTF.GetChild(i).gameObject.name);

            //首先先遍历是否符合条件
            if (GOTF.GetChild(i).gameObject.name == name)
            {
                //print("已经找到了");
                childTF = GOTF.GetChild(i);
                return childTF;
            }

            //遍历没有符合的在递归下一层
            childTF = GetNameFindGameObject(GOTF.GetChild(i), name);
        }

        return childTF;
    }
}


回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-9 17:34:20 | 显示全部楼层
//更新代码-M2NGUIResourcesLoad_script.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class M2NGUIResourcesLoad_script : MonoBehaviour
{
    //资源加载类脚本(一般称为工厂类)

    public Object[] AllWeapons;

    //创建字典用于缓存,优化代码
    private Dictionary<string, Object> AllWeaponsList = new Dictionary<string, Object>();

    public Object[] AllCharacter;

    public Texture[] AllClother;

    public Object[] AllAnimation;

    /// <summary>
    /// 加载武器方法
    /// </summary>
    /// <param name="resourcesName">资源名称</param>
    /// <returns></returns>
    public Object Weaponsload(string resourcesName)
    {
        //使用集合作为武器的缓存保存起来,再次调用的时候如果有调用过,则直接在集合中return即可
        if (AllWeaponsList.ContainsKey(resourcesName))
        {
            return AllWeaponsList[resourcesName];
        }

        //加载武器资源到武器数组中
        AllWeapons = Resources.LoadAll("Weapons/");

        for (int i = 0; i < AllWeapons.Length; i++)
        {
            if (AllWeapons.name == "wp_"+resourcesName)
            {
                //存放在集合中,下次如果再次使用加载武器就不用使用for遍历浪费资源--优化方法
                AllWeaponsList.Add(resourcesName, AllWeapons);

                return AllWeapons;
            }
        }
        return null;
    }

    /// <summary>
    /// 加载人物方法
    /// </summary>
    /// <param name="resourcesName">资源名称</param>
    public Object Characterload(string resourcesName)
    {
        AllCharacter = Resources.LoadAll("Prefabs/");

        for (int i = 0; i < AllCharacter.Length; i++)
        {
            if (AllCharacter.name == "mon_" + resourcesName)
            {
                return AllCharacter;
            }
        }


        print(AllCharacter.Length);

        return null;
    }

    /// <summary>
    /// 加载衣服方法
    /// </summary>
    /// <param name="resourcesName">资源名称</param>
    public Texture Clotherload(string manName,string resourcesName)
    {

        AllClother = Resources.LoadAll<Texture>("Clother/");

        for (int i = 0; i < AllClother.Length; i++)
        {
            if (AllClother.name == "mon_"+manName +"_"+ resourcesName)
            {
                return AllClother;
            }
        }

        return null;
    }

    //获取人物动画的方法-废弃
    public Object Animationload(GameObject man,string resourcesName)
    {
        return null;
    }
}


回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-11-9 22:18:27 | 显示全部楼层
工程文件(适用于unity 2019版本):
链接:https://pan.baidu.com/s/1OSuTm4BgVmS_8NXAOxzhAw
提取码:n49f

回复 支持 反对

使用道具 举报

游客
回复
*滑块验证:

DA论坛飞机票来了~
快速回复 返回顶部 返回列表