当前位置: 首页 > article >正文

自由学习记录(33)

OSI模型是网络通信的基本规则
TCP/IP协议是基于OSI模型的工业实现

数据通信模型

分散式因为数据容易不一致,显然被早早淘汰


客户端
用户使用的设备(计算机、手机、平板等等)
客户端应用程序
用户使用的设备上安装的应用程序,用户会直接使用操作的内容
比如各种游戏、聊天软件、外卖软件等等
往往提到客户端都泛指的是客户端应用程序

 网络游戏开发的客户端和服务端

前三个是制造商编号,也就是说想制造网卡,就必须先向这个协会申请到前面的编号,而Mac地址后三位就相当于网卡的个人身份证了

私网IP(局域网内的IP,比如电脑用网线连着多个其他的设备)不能上网,只用于局域网内通信

Mac地址 (Media Access Control Address)
直译为媒体存取控制地址,也称局域网地址,Mac地址,以太网地址,物理地址

早期不用IP地址都可以,Mac地址就可以对应到设备(这是一种“广播”,也就是周围所有设备都会受到这个信息,再判断是不是自己的----缺点也很明显了,所以产生了IP地址辅助Mac地址)


在OSI模型中,第三层网络层负责IP地址,第二层数据链路层则负责Mac地址

Mac地址唯一标识一个网卡的,一台设备可以有多个网卡,每个网卡都会有一个唯一的Mac地址

一台设备的 多个应用程序 连入网络,必须一个应用程序对应一个唯一的端口号

-但只知道了IP地址,并不是说就知道了发信息收信息的是哪一个设备,正如下面的所说,只能知道是在你家这个局域网之下,所以就会需要有端口号

家里的一群设备连接了相同的wifi,也就是进入了相同的局域网地址,所以局域网内的所有设备 的IP 地址都一样

IP地址分配很多时候不是我们自己分配的

万维网:是基于因特网的网站和网页统称

 广域网WAN连接不同国家

MAN城域网连接不同的城市区域

网络并不是像磁场那样的,而是任意两台电脑产生了数据连接,这时第三台独立电脑想要加入其中,则第三台电脑加入了“网络”,没有两台以上的电脑,则不会存在此时此刻的“网络”

局域网

网络的概念,是将孤立的各个设备连接起来的 功能总体

网络开发的话,对线程和二进制的持久化,这两个的理解是很重要的

Json--数据持久化

能处理 DictionaryList 等复杂类型。

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式

数据持久化、配置存储和网络通信

Unity 内置的 JsonUtility 类进行 JSON 序列化和反序列化

using UnityEngine;

[System.Serializable]
public class PlayerData
{
    public string playerName;
    public int playerLevel;
    public float health;
}

public class JSONExample : MonoBehaviour
{
    void Start()
    {
        // 创建一个 PlayerData 对象
        PlayerData player = new PlayerData();
        player.playerName = "Alice";
        player.playerLevel = 10;
        player.health = 100f;

        // 序列化为 JSON 字符串
        string jsonString = JsonUtility.ToJson(player);

        // 打印结果
        Debug.Log(jsonString);
    }
}

打印结果

public class JSONExample : MonoBehaviour
{
    void Start()
    {
        // JSON 字符串
        string jsonString = "{\"playerName\":\"Alice\",\"playerLevel\":10,\"health\":100}";

        // 从 JSON 字符串反序列化为对象
        PlayerData player = JsonUtility.FromJson<PlayerData>(jsonString);

        // 打印反序列化后的结果
        Debug.Log("Player Name: " + player.playerName);
        Debug.Log("Player Level: " + player.playerLevel);
        Debug.Log("Health: " + player.health);
    }
}

保存和加载 JSON 文件

using UnityEngine;
using System.IO;

public class JSONFileExample : MonoBehaviour
{
    private string filePath;

    void Start()
    {
        filePath = Application.persistentDataPath + "/playerData.json";  // 获取存储路径

        // 创建一个 PlayerData 对象
        PlayerData player = new PlayerData();
        player.playerName = "Bob";
        player.playerLevel = 5;
        player.health = 75f;

        // 将 PlayerData 对象序列化为 JSON 字符串
        string jsonString = JsonUtility.ToJson(player);

        // 保存到文件
        SaveToFile(jsonString);

        // 从文件加载 JSON 数据
        string loadedJson = LoadFromFile();

        // 将加载的 JSON 字符串反序列化为 PlayerData 对象
        PlayerData loadedPlayer = JsonUtility.FromJson<PlayerData>(loadedJson);

        // 打印加载的数据
        Debug.Log("Loaded Player Name: " + loadedPlayer.playerName);
        Debug.Log("Loaded Player Level: " + loadedPlayer.playerLevel);
        Debug.Log("Loaded Health: " + loadedPlayer.health);
    }

    void SaveToFile(string json)
    {
        // 写入 JSON 数据到文件
        File.WriteAllText(filePath, json);
        Debug.Log("Data saved to: " + filePath);
    }

    string LoadFromFile()
    {
        // 从文件读取 JSON 数据
        if (File.Exists(filePath))
        {
            return File.ReadAllText(filePath);
        }
        else
        {
            Debug.LogWarning("File not found!");
            return "{}";  // 返回空的 JSON 对象
        }
    }
}

Json字符串的存储和读取就是很基本的语言使用File,没有引用额外的API

Unity 中,JSON格式的处理,JsonUtility 的功能相对有限,可能无法满足复杂数据结构的需求,

这时可以考虑使用第三方的Json库

LitJson可以不用给类添加serializable

Newtonsoft.Json(也叫 Json.NET

序列化为Json字符串

反序列化为类对象

LitJson

转换的实例对象可以不用在类定义上添加特性

手动Jso序列化的n的SimpleJson

二进制--数据持久化

二进制格式,存入、取出 过程中的 数据格式

C# 中,可以使用 BinaryFormatter 类来实现对象的序列化和反序列化

 

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable] // 必须标记类为可序列化
class Person
{
    public string Name;
    public int Age;
}

class Program
{
    static void Main()
    {
        // 创建对象
        Person person = new Person { Name = "Alice", Age = 30 };
        
        // 创建文件流
        using (FileStream fs = new FileStream("person.dat", FileMode.Create))
        {
            // 创建二进制格式化对象
            BinaryFormatter formatter = new BinaryFormatter();
            // 序列化对象到文件
            formatter.Serialize(fs, person);
        }
        
        Console.WriteLine("对象已序列化并保存到 person.dat 文件中");
    }
}

using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

[Serializable]
class Person
{
    public string Name;
    public int Age;
}

class Program
{
    static void Main()
    {
        // 从文件流中读取
        using (FileStream fs = new FileStream("person.dat", FileMode.Open))
        {
            // 创建二进制格式化对象
            BinaryFormatter formatter = new BinaryFormatter();
            // 反序列化对象
            Person person = (Person)formatter.Deserialize(fs);
            
            Console.WriteLine($"Name: {person.Name}, Age: {person.Age}");
        }
    }
}

----------

线程

线程是程序中用于并行执行任务的基本单元。通过多线程,您可以在程序中同时执行多个任务

I/O 密集操作 或 多 任务同时运行

每个线程都可以执行一段代码,称为线程任务

(操作系统层面)线程与进程不同,一个进程可以包含多个线程,多个线程共享进程的资源

在多核 CPU 上并行

C# 中的线程 Thread

创建

using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        // 创建一个新线程,执行任务方法
        Thread thread = new Thread(Task);
        thread.Start();  // 启动线程
    }

    // 线程将执行的任务
    static void Task()
    {
        Console.WriteLine("线程开始执行");
    }
}

一个线程 传递参数,可以通过 ThreadStart 委托或使用 ParameterizedThreadStart

Thread thread = new Thread(new ParameterizedThreadStart(Task));

thread.Start("Hello, Thread!"); // 启动线程并传递参数

using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        // 传递参数给线程
        Thread thread = new Thread(new ParameterizedThreadStart(Task));
        thread.Start("Hello, Thread!");  // 启动线程并传递参数
    }

    // 线程执行的方法,接受一个参数
    static void Task(object message)
    {
        Console.WriteLine(message);  // 打印传入的参数
    }
}

线程的结束等待     thread.Join();

using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        Thread thread = new Thread(Task);
        thread.Start();  // 启动线程
        thread.Join();   // 等待线程执行完毕
        Console.WriteLine("主线程继续执行");
    }

    static void Task()
    {
        Console.WriteLine("子线程执行中");
    }
}

取消线程--通过标志位或使用 CancellationToken(一个简单的函数外bool控制while循环)

using System;
using System.Threading;

class Program
{
    static bool shouldStop = false;

    static void Main(string[] args)
    {
        Thread thread = new Thread(Work);
        thread.Start();

        Thread.Sleep(2000);  // 让线程工作一段时间
        shouldStop = true;  // 设置标志,要求线程停止
    }

    static void Work()
    {
        while (!shouldStop)
        {
            Console.WriteLine("线程执行中...");
            Thread.Sleep(500);
        }
        Console.WriteLine("线程已停止");
    }
}

线程同步

lock 关键字来保护共享资源

using System;
using System.Threading;

class Program
{
    static int counter = 0;
    static object lockObj = new object();

    static void Main(string[] args)
    {
        Thread thread1 = new Thread(Increment);
        Thread thread2 = new Thread(Increment);

        thread1.Start();
        thread2.Start();

        thread1.Join();
        thread2.Join();

        Console.WriteLine("最终计数:" + counter);
    }

    static void Increment()
    {
        // 使用 lock 来同步线程,防止数据竞争
        lock (lockObj)
        {
            for (int i = 0; i < 1000; i++)
            {
                counter++;
            }
        }
    }
}

线程池

允许重用线程(ThreadPool 类)

using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        // 将任务委托给线程池
        ThreadPool.QueueUserWorkItem(Work);
    }

    static void Work(object state)
    {
        Console.WriteLine("线程池中的任务执行");
    }
}

ThreadPool.QueueUserWorkItem 将任务添加到线程池,线程池会自动管理线程的创建和销毁

------

------

UGUI是使用最广的,可能90%以上

元件(GObject)是构建用户界面的基本单元。 每个元件都有一组属性和方法,用于控制其在界面中的表现和行为。

UI管理器总的来说是最重要的,各UI的使用套路都是差不多的,写代码理思路的时候以面向对象的思想去写,

------

自动生成的代码通常包括对 UI 元素的绑定和访问方法,方便您在代码中操作 UI 元素。 重新生成代码时,FGUI 会根据当前的 UI 资源状态生成新的代码文件,覆盖原有的代码文件。

重新生成代码操作用于根据您在 FGUI 编辑器中创建的 UI 资源,自动生成对应的 C# 代码,以便在 Unity 中进行编程操作。

发布操作用于将您在 FGUI 编辑器中创建的 UI 资源导出为二进制文件和纹理集,以便在 Unity 等引擎中使用。 发布时,您可以选择发布所有包,或者仅发布选中的包。 发布后,生成的二进制文件(通常以 .fui 为扩展名)和纹理集(通常以 .atlas 为扩展名)将被保存到指定的输出目录。

有发布和重新生成代码

改正关联之后,重新发布(只是组件调整,不用改代码的)

分辨率自适应的自测,

ugui和ngui都需要自己去注意层级,但FGUI在drawcall上的调整就便利很多

重点是这里的动效播放是需要0.25秒的(也就是自己设置 的),而这里设置的意思是只有这个动效播放完,才会调用onshown方法,也就是把登录面板的账号密码变为data里存的数据

注册面版传递注册成功的账号密码是一帧就结束了,而等动效播放完的0.25秒再调用的迟来的shown方法,会再次把数值改回原本的样子,也就是清空了

这里的data此时并没有改变,还是空的,所以onshow---doshowanimation--Window调用

这里修改的doshowAnimation重写,让自带的show方法先执行,先激活这个组件到unity里面显示,之后才调用动效的播放,这样做避免了注册传递的数值被show方法覆盖

这个方法会执行onshown,而onshown在

所以在调用面板出来的时候,注册面板的数值没有成功赋值到登录面板显示 ,在这里的渐显隐要注意的就是对数值的修改,因为数值是一直被显示的,不会自己改,是说显示1才显示1的

发现自身的值需要修改,但是暴露给外部又感觉封装的不好,这样写一个函数在内部,相比破坏封装的危险,这样额外多写一个函数的麻烦并不算什么

活用字典

自定义序列化:如果需要控制序列化过程,可以实现 ISerializable 接口。

继承关系:如果一个类继承自标记为 [Serializable] 的类,则派生类也会被视为可序列化,除非显式地标记为 [NonSerialized]

C# 中,[Serializable] 是一个特性(Attribute),用于标记类或结构体,使其能够被序列化。序列化是将对象的状态转换为可存储或传输的格式的过程。

注意,MakeFullScreen 方法是 GObject 类的方法,而 contentPaneWindow 类的属性。

因此,您需要确保在设置 contentPane 后,再调用 MakeFullScreen 方法来实现全屏效果。

FairyGUI 中,GObject 类提供了 MakeFullScreen 方法,用于将对象设置为全屏大小(逻辑屏幕)。

包名,然后组件名

using FairyGUI;

public class MyWindow : Window
{
    protected override void OnInit()
    {
        // 加载名为 "MyPackage" 的包中的 "MainComponent" 组件
        GComponent component = UIPackage.CreateObject("MyPackage", "MainComponent").asCom;

        // 设置窗口的 contentPane 为加载的组件
        this.contentPane = component;

        // 其他初始化操作...
    }
}

contentPane 属性:contentPane 是 Window 类中的一个重要属性,表示当前窗口的主要内容区域。在这里,您需要掌握如何操作这个区域来添加、删除或更新其中的 UI 元素。

MakeFullScreen():确保 UI 组件在不同分辨率下正常显示。

发布的文件夹可以自定义,所以放到unity项目文件夹里会方便很多

红点表示 已经设置成需要导出了

检测关联是否正确,是否可以在不同分辨率中正确显示

拼了面板之后,点测试,可以切换设备

在组件中直接引用原组件

自建的Window组件里的

新建的Button组件

后续的panelwindow都是先继承window类,然后初始化对应的包,再关联对应的组件

Carey


http://www.kler.cn/a/526718.html

相关文章:

  • SSM开发(三) spring与mybatis整合(含完整运行demo源码)
  • 初二回娘家
  • 当当网近30日热销图书的数据采集与可视化分析(scrapy+openpyxl+matplotlib)
  • maven、npm、pip、yum官方镜像修改文档
  • 基于Python的人工智能患者风险评估预测模型构建与应用研究(下)
  • 跨境数据传输问题常见解决方式
  • INCOSE需求编写指南-附录 B: 首字母缩略词和缩写
  • 详解python的单例模式
  • DeepSeek-V3技术报告解读
  • Cocos Creator 3.8 2D 游戏开发知识点整理
  • Sqoop支持ORC文件格式
  • AI大模型开发原理篇-4:神经概率语言模型NPLM
  • 【C++题解】1055. 求满足条件的整数个数
  • GWO优化GRNN回归预测matlab
  • 165. 比较版本号
  • 《解码AI大模型涌现能力:从量变到质变的智能跃迁》
  • 如何利用Docker和.NET Core实现环境一致性、简化依赖管理、快速部署与扩展,同时提高资源利用率、确保安全性和生态系统支持
  • Deepseek r1模型对医疗大模型的发展有什么影响?
  • 线程池以及在QT中的接口使用
  • Carla-ModuleNotFoundError: No module named ‘agents.navigation‘
  • Spring Boot - 数据库集成06 - 集成ElasticSearch
  • 【懒删除堆】力扣2349. 设计数字容器系统
  • 【C语言进阶】- 动态内存管理
  • 【memgpt】letta 课程5:可编程的agent内存
  • [HOT 100] 0003. 无重复字符的最长子串
  • 本地AI模型:未来智能设备的核心驱动力