首页 > 其他分享 >Unity相关学习

Unity相关学习

时间:2023-08-16 16:33:05浏览次数:45  
标签:int void event 学习 Unity delegate 相关 序列化 public

实现C#委托/事件

  1. 声明的委托与时间&通知者执行的方法参数类型要匹配
  2. 参数声明要继承EventArgs
using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApplication1
{
    //声明一个委托
    public delegate void TimeEventHandler(object obj, TimeEventArgs args);
    class Program
    {
        static void Main(string[] args)
        {
            Clock clock = new Clock(); //实例化一个时钟            
            MyClassEventHandler tehc = new MyClassEventHandler(); //实例化一个观察者类
            //将事件跟我们定义的观察者进行连接
            //这样,clock就会知道,每当TimeChanged事件被触发,就会去通知这个观察者
            //注意我们连接的时候使用的并不是直接的观察者类实例中的ShowTime()方法
            //而是一个委托,并在这个委托中传递ShowTime()方法,这也是"委托"的真正意义所在:
            //我有一个方法,但我委托你来帮我关联到事件,因为事件只会直接跟委托打交道,
            //而不是观察者的具体某个方法
            clock.TimeChanged += new TimeEventHandler(tehc.ShowTime);
            clock.go();
        }
    }

    //TimeEventArgs是我们自己定义的一个类,用于保存事件中的参数.这里我们分别保存时间的时分秒
    public class TimeEventArgs:EventArgs
    {
        private int hour;
        private int minute;
        private int second;
        public TimeEventArgs(int hour,int minute,int second)
        {
            this.hour = hour;
            this.minute = minute;
            this.second = second;
        }
        public int Hour{
            get {
                return this.hour;
            }
        }
        public int Minute {
            get {
                return this.minute;
            }
        }
        public int Second {
            get {
                return this.second;
            }
        }
    }
    //观察者类,它有一个符合我们上面定义的"委托"的方法
    //也就是void ShowTime(object obj,TimeEventArgs args)
    //从这个方法的定义可以看到,我们只会关心返回类型和方法的参数,而方法名称则无所谓
    class MyClassEventHandler
    {
        public void ShowTime(object obj,TimeEventArgs args)
        {
            Console.WriteLine("现在时间:"+args.Hour+":" + args.Minute + ":" + args.Second);
        }
    }

    //时钟类
    class Clock
    {
        //我们在这个类中定义了一个"TimeChanged"事件,注意其前面有两个关键字"event"和"TimeEventHandler"
        //其中event表示这是一个事件,而不是方法或属性,TimeEventHandler则指出,谁要监听TimeChanged事件,它就必须有一个符合TimeEventHandler(委托)的方法
        public event TimeEventHandler TimeChanged;
        public Clock()
        {
            //注意,这里的null的含义是指TimeChanged事件当前还没有观察者关注它
            //如果某个观察者要关注TimeChanged事件,它必须要让这个事件知道,方法是使用操作符"+="来借助委托将其加载到事件上
            TimeChanged = null; 
        }

        //时钟开始走动,我们的目标是每秒钟触发一次TimeChanged事件
        public void go()
        {
            DateTime initi = DateTime.Now;
            int h1 = initi.Hour;
            int m1 = initi.Minute;
            int s1 = initi.Second;
            while (true)
            {
                DateTime now = DateTime.Now;
                int h2 = now.Hour;
                int m2 = now.Minute;
                int s2 = now.Second;
                if (s2 != s1)
                {
                    h1 = h2;
                    m1 = m2;
                    s1 = s2;
                    //首先建立一个TimeEventArgs对象来保存相关参数,这里是时分秒
                    TimeEventArgs args = new TimeEventArgs(h2, m2, s2);
                    //注意这种写法,这一句是用来触发事件,事件不是类,所以不用使用"new"关键字,而且我们看到,这里TimeChanged的两个参数跟我们的委托(TimeEventHandler)是一致的
                    //其中第一个参数是触发这个事件的对象,我们这里使用的是一个时钟实例(this)
                    //clock.go() -> this就是clock变量的地址
                    TimeChanged(this, args);
                }
            }
        }
    }
}

delegate:

//实现一个委托
public delegate void myDelegate(int num);

public myDelegate m_delegate;

m_delegate += MyFun;

public void MyFun(int num)
{
  Debug.Log("my func: " + num);
}

//delegate可以使用"="将所有已经订阅的取消
m_delegate = MyFun1;  //MyFun订阅被取消,只有MyFun1在订阅中

Event:

public event myDelegate m_event;

m_event += MyFun;
m_event = MyFun;  //错误

EventHandler:

//这是它的定义
//@sender: 引发事件的对象
//@e: 传递的参数
public delegate void EventHandler(object sender, EventArgs e);

//使用
public event EventHandler m_event;  //修改自定义委托类型为EventHandler

Action:

//Action是系统预定义的一种委托,无返回值,参数在<>中传入
public Action<int> m_action;

//Compare:
public delegate void myDelegate(int num);
public Action<int> m_action;
//1,Action省略了void,因为它本身就是无返回值
//2, Action的参数在<>中定义的,delegate就是传统定义
//3,delegate要用关键字,然后自定义一个委托名字。而Action委托名字已定。不需要delegate关键字。

Interface:

用法:多继承

C#中接口可以多继承,接口之间可以互相继承和多继承。 普通类和抽象类可以继承接口。 一个类可以同时继承一个类和多个接口,但是接口不能继承类

interface Interface1(){
    //接口方法不需要实现
    void methodPrint1();
}

interface Interface2(){
    void methodPrint2();
}

class BaseClass : Interface1, Interface2
{
    public override void methodPrint1()
    {
    }

    public override void methodPrint2()
    {
    }
}

class BaseClass2: Interface2
{
    public override void methodPrint2()
    {
    }
}

Example:

public delegate void myDelegate(int num);
public class Event :MonoBehaviour
{
    private void Start(){
        DelegateFunc();
        EventFunc();
        EventHandlerFunc();
        ActionFunc();
    }

    //delegate
    public myDelegate m_delegate;
    void DelegateFunc(){
        m_delegate += MyEventFun;
        m_delegate(1);

        m_delegate = (d) =>{
            Debug.Log("m_delegate : " + d);
            };
        m_delegate(2);
    }

    //Event
    public event myDelegate m_event;
    void EventFunc(){
        m_event += MyEventFun;
        m_event(3);

        m_event = (d) =>{Debug.Log("m_event : " + d);};
        m_event(4);
    }

    //EventHandler
    public event EventHandler m_EventHandle;
    void EventHandlerFunc(){
        m_EventHandle += MyEventFun;
        m_EventHandle(5, new EventArgs());

        m_EventHandle += (o, e) =>{ Debug.Log("m_EventHandle: " + Convert.ToInt32(o) + "\t " + e.ToString());};
        m_EventHandle(6, new EventArgs());
    }

    //Action   只需要申明参数即可,直接调用Action对象,即可调用到响应函数。Action最好用一个单例类管理
    public Action<int> m_action;
    void ActionFunc(){
        m_action += MyEventFun;
        m_action(7);

        m_action = (d) =>{Debug.Log("m_action : " + d);};
        m_action(8);
    }

    public void MyEventFun(int num)
    {
        Debug.Log("my func1: " + num);
    }

    public void MyEventFun(object sender, EventArgs e)
    {
        Debug.Log("my func2: " + Convert.ToInt32(sender) + "\t " + e.ToString());
    }
}

可复用代码:

public static class GameEventDefine
{
    public static Action Event_OnSelectNextPlayer;
    public static Action Event_OnSelectPrePlayer;

    public static Action<bool> Event_OnShowSelectCharacter;
}
private void Start()
{
    GameEventDefine.Event_OnSelectPrePlayer += OnSwitchPlayerPre;
    GameEventDefine.Event_OnSelectNextPlayer += OnSwitchPlayerNext;
    GameEventDefine.Event_OnShowSelectCharacter += OnShowChacterSelectScene;
}

private void OnSwitchPlayerNext()
{
    mCurSelectPlayerIndex++;
    if (mCurSelectPlayerIndex >= mTotalSelectPlayerCount)
        mCurSelectPlayerIndex = 0;
    SetPlayerIndex(mCurSelectPlayerIndex);
}

private void OnSwitchPlayerPre()
{
    mCurSelectPlayerIndex--;
    if (mCurSelectPlayerIndex < 0)
        mCurSelectPlayerIndex = mTotalSelectPlayerCount - 1;
    SetPlayerIndex(mCurSelectPlayerIndex);
}

private void SetPlayerIndex(int index)
{
    YXUnityLog.LogInfo(TAG, $"SetPlayerIndex index: {index}");
    float xvalue = index * 5;
    mTrsSelectRoot.transform.localPosition = new Vector3(xvalue, 0f, 0f);
}

public void OnShowChacterSelectScene(bool show)
{
    mRoot.SetActive(show);
}

序列化

  • C#序列化和Unity序列化:

    • 序列化是.NET运行时环境用来支持用户定义类型的流化的机制,目的是以某种存储形式使自定义对象持久化,或者将这种对象从一个地方传输到另一个地方。
    • 在Unity中比较直观的理解就是面板可以看到的数据都是序列化成功的数据
  • 序列化使用场景:

    • Unity中需要在控制面板挂载但是不被其他类引用的时候(防止滥用public)
    • C#中需要保存的数据(存储为二进制文件或者.xml文件)
  • Unity和C#用起来感觉有区别的原因是Unity Editor本身就是基于序列化的可视化窗口,所以他们底层目的还是相同的

  • 例子

public class Test :Monobehavior
{
    public int  a;                              //序列化,显示
    private int b;                              //不序列化,不显示
    [SerializeField] int c;                     //序列化,显示
    [HideInInspector] public int d;             //序列化,不显示
    [NonSerialized] public int e;               //不序列化,不显示
    public Test2 test2;                         //序列化,显示(可序列化的部分)
}
 
[Serializable]
public class Test2
{
     public int aa;
     private int bb;
}

image


//.NET环境下,序列化就是把自定义数据类型持久化并可以转换成二进制文件传输

[Serializable]
public class DemoClass
{
    public int _id;
    public string _myName;
    public DemoClass(int id, string myName)
    {
        _id = id;
        _myName = myName;
    }
    public DemoClass()
    {
    }
    public void Output()
    {
        Debug.LogError(_id);
        Debug.LogError(_myName);
    }
}

// 将对象写进二进制文件,存储
void WriteTest()
{
    DemoClass demo = new DemoClass (100, "RCD");
    FileStream fs = new FileStream ("demo.bin", FileMode.OpenOrCreate);
    BinaryFormatter bf = new BinaryFormatter ();
    bf.Serialize (fs, demo);
    fs.Close ();
    Debug.LogError ("write done");
}

//读操作
void ReadTest()
{
    FileStream fs = new FileStream("demo.bin", FileMode.Open);
    BinaryFormatter bf = new BinaryFormatter();
    DemoClass demo = bf.Deserialize(fs) as DemoClass;
    fs.Close();
    demo.Output();
}

unity 添加Json库的办法

实践发现通过NuGet包管理工具添加在unity中是不识别的,虽然vs不报错,但是editor会报错

正确的姿势:

window -> package manager->+号 ->add package from git URL...

com.unity.nuget.newtonsoft-json

image

unity 单例SingleMonbehavior实现

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

namespace gslb.core.util
{
    public class SingletonMonoBehaviour<T> : MonoBehaviour where T : MonoBehaviour
    {
        private static object _singletonLock = new object();
        private static T _instance;

        public static T Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_singletonLock)
                    {
                        T[] singletonInstances = FindObjectsOfType(typeof(T)) as T[];
                        if (singletonInstances.Length > 1)
                        {
                            if (Application.isEditor)
                                Debug.LogError("MonoSingleton<T>.Instance: Only 1 singleton instance can exist in the scene. Null will be returned.");
                            return null;
                        }

                        if (singletonInstances.Length == 0)
                        {
                            GameObject singletonInstance = new GameObject();
                            _instance = singletonInstance.AddComponent<T>();
                            singletonInstance.name = "(singleton) " + typeof(T).ToString();
                        }
                        else
                            _instance = singletonInstances[0];
                    }

                    _instance = FindObjectOfType<T>();
                }

                return _instance;
            }
        }

        protected virtual void OnEnable()
        {
            if (Instance != this)
            {
                Destroy(this);
            }
        }
    }
}

标签:int,void,event,学习,Unity,delegate,相关,序列化,public
From: https://www.cnblogs.com/jobshenlei/p/17635412.html

相关文章

  • Unity-unity导出gltf模型
    1.首先是用这个获取源码gitclonehttps://github.com/KhronosGroup/UnityGLTF.git2.打开项目之后,选择Samples下面的一个场景,在Console有超多的错误信息。3.编译GLTFSerialization,最后生成的dll库放在了UnityGLTF\UnityGLTF\Assets\UnityGLTF\Runtime\Plugins目录下了;Tests引......
  • Unity UGUI的InputField(输入框)组件的介绍及使用
    UGUI的InputField(输入框)组件的介绍及使用1.什么是UGUI的InputField组件?UGUI的InputField组件是Unity中的一个用户界面组件,用于接收用户的输入。它可以用于创建文本输入框、密码输入框等功能。2.UGUI的InputField组件的工作原理UGUI的InputField组件通过监听用户的输入事件,用......
  • if语句条件判断大集合--------------------------------------python语言学习
    准备数据: ##实现成绩大于等于600为优秀,其他为普通等级上代码:importpandasaspddf=pd.read_excel('C:/Users/Administrator/Desktop/test1.xlsx',header=1)defscore_if(score):ifscore>=600:a="优秀"returnaelse:a="普通"......
  • 踏上 AI 学习之旅:掌握人工智能的 4 个步骤
    人工智能(AI)已成为一种变革力量,正在重塑行业并改善我们生活的各个方面。鉴于人工智能的复杂性和快速发展,学习人工智能似乎是一项艰巨的任务。然而,通过正确的方法和奉献精神,任何人都可以踏上成功的人工智能学习之旅。在本文中,我们将概述四个基本步骤,以帮助您掌握AI的基础知识,并让......
  • TZC-400学习
    ARM®CoreLink™TZC-400TrustZone®AddressSpaceController该篇文档的翻译及一些总结说明:https://www.cnblogs.com/lvzh/p/16582717.htmlTZC400学习总结这是个大佬的总结:https://blog.csdn.net/weixin_42135087/article/details/107161137TZC400总结之于SOC安全域https......
  • python编程从入门到实践(第2版)学习笔记(变量,字符串)
    变量变量是一种可以赋给值的标签。每一个变量都指向一个相关联的值,下列代码中message即为变量,指向的值为“HelloPythonworld!”message="HelloPythonworld!"print(message)第二行的print()函数用于打印输出这个message变量所关联的值。且变量的值是可以修改的,p......
  • 数据仓库的相关学习
    1、数据仓库概念--为了分析数据数仓专注分析:出现:支持分析、面向分析:2、数据仓库的主要特征面向主题性:集成性:非易失性(非易变性):时变性:3、数据仓库主流开发语言--SQL介绍......
  • 最小表示法学习笔记
    定义一个字符串\(S\)的最小表示法为该字符串所有循环同构字符串中字典序最小的一个。比如:\(abca\),对于他,循环同构字符串就有\(aabc\),\(caab\),\(bcaa\),其中字典序最小的是\(aabc\)。那么我们说\(aabc\)就是\(abca\)最小表示法。算法流程介绍考虑对于一对子串\(A,B\),......
  • docker命令学习
    docker镜像命令:                      退出:exit           退出但是不停止运行:Ctrl+p+q 删除容器:rm容器iddockerimages  查看镜像dockersearch 镜像名称 ......
  • 2023年Java学习路线,23分钟视频讲解,快速掌握Java课程体系
    自学Java开发并非易事,特别是当你刚开始学习时,需要面对的困难似乎比预期的要多得多。但是,如果你有一个系统的学习路线和计划,并注重实践,那么你将会逐渐掌握Java,有效的提高学习效率。深知大家自学Java的苦,苦于没有系统的知识体系,不知道该学什么?看哪个视频比较好?因此,老杜精心录制了一版......