【C#基础】unity中结构体的使用

【C#基础】unity中结构体的使用

结构体(Struct)是值类型数据结构,在栈上分配内存,可以包含字段,属性,方法,构造函数。结构体可以实现接口,但是不能继承。在Dots里有大量依靠Struct实现接口来定义Entities数据类型和实现逻辑。

一、结构体的基本使用

  • 定义结构体
  • 结构体初始化
  • 结构体方法
  • 结构体扩展方法

1.定义结构体

结构体一般用于小型的数据类型,下面定义一个双精度的三维坐标数据为例。

c 复制代码
Public struct DoubleVec {}

2.结构体初始化

(1)通常通过构造函数对结构体进行初始化,也可以单独定义后赋值。

结构体

c 复制代码
public struct DoubleVec
{
    public double x;
    public double y;
    public double z;

    //构造函数
    public DoubleVec(double x, double y, double z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }
}

初始化和单独赋值

c 复制代码
    DoubleVec doubleVec1;
    DoubleVec doubleVec2;
    void Start()
    {
        doubleVec1 = new DoubleVec(1, 1, 1);
        doubleVec2.x = 3;
        Debug.Log("doubleVec1.x=" + doubleVec1.x);
        Debug.Log("doubleVec2.x=" + doubleVec2.x);
    }

结果

c 复制代码
doubleVec1.x=1
doubleVec2.x=3    

(2)没有对结构体进行初始化或者赋值,直接调用结构体的字段

重新定义一个字段类型多的结构体

c 复制代码
public struct DoubleVec
{
    public float x;
    public float y;
    public double z;
    public string name;
    public Vector3 vec;
    public bool bo;
    public int[] ints;
}

直接使用字段

c 复制代码
    DoubleVec doubleVec2;
    void Start()
    {
        Debug.Log("doubleVec2.y=" + doubleVec2.y);
        Debug.Log("doubleVec2.vec=" + doubleVec2.vec);
        Debug.Log("doubleVec2.name=" + doubleVec2.name);
        Debug.Log("doubleVec2.ints=" + doubleVec2.ints);
        Debug.Log("doubleVec2.bo=" + doubleVec2.bo);
        Debug.Log("doubleVec2.x=" + doubleVec2.x);
    }

结果

c 复制代码
    doubleVec2.y=0 //浮点类型初始为0
    doubleVec2.vec=(0.00, 0.00, 0.00)//vecter初始为原点
    doubleVec2.name= //字符串为空
    doubleVec2.ints= //数组为空
    doubleVec2.bo=False   //bool为false
    doubleVec2.x=0

(3)构造函数

实例构造函数:初始化字段信息,构造函数参数必须对没有字段进行赋值

静态构造函数:当结构体构造实例时,静态构造函数会自动调用一次;不带任何参数,不带修饰符。

c 复制代码
public struct DoubleVec
{
    public double x;
    public double y;
    public double z;

    //构造函数
    public DoubleVec(double x, double y, double z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    //静态构造函数
    static DoubleVec()
    {
        Debug.Log("被调用");
    }
}

3.结构体方法

  • get方法
  • 结构体传参方法
  • 逻辑运算

(1)get方法

可以直接在结构体变量后使用,下面以求模长为例

c 复制代码
   DoubleVec doubleVec1;
   void Start()
    {
        doubleVec1 = new DoubleVec(1, 1, 1);
        //这里直接可以点出方法
        double mag= doubleVec1.Magnitude;
        Debug.Log("mag=" + mag);
 
    }

创建的方法

c 复制代码
public struct DoubleVec
{
    public double x;
    public double y;
    public double z;

    //构造函数
    public DoubleVec(double x, double y, double z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }
   //必须用get方法给方法赋值
    public double Magnitude {
        get {return  magnitude(); }
    }
    //求模长的方法
     double magnitude()
    {
        double a = getLength(x, y);
        double b = getLength(a, z);
        return b;
        double getLength(double a, double b)
        {
            return Math.Sqrt(a * a + b * b);
        }
    }
}

该方法只能使用结构体变量的字段进行逻辑处理,与结构体的字段关联

(2)结构体传参方法

可以在结构类型后面点出方法,传入参数进行逻辑处理,同样以求模长为例

c 复制代码
  DoubleVec doubleVec1;
   void Start()
    {
        doubleVec1 = new DoubleVec(1, 1, 1);
        //这里是同结构体类型点出方法,参数为结构体变量
        double mag= DoubleVec.MagnitudeVec(doubleVec1);
        Debug.Log("mag=" + mag);
 
    }

创建方法

c 复制代码
public struct DoubleVec
{
    public double x;
    public double y;
    public double z;

    //构造函数
    public DoubleVec(double x, double y, double z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }
   //这里要用静态方法,参数与结构体本身的字段没有关系
    public static double MagnitudeVec(DoubleVec vec)
    { 
        return magnitude(vec);
    }
    //运算方法也要静态
    static double magnitude(DoubleVec vec)
    {
        double a = getLength(vec.x, vec.y);
        double b = getLength(a, vec.z);
        return b;
        double getLength(double a, double b)
        {
            return Math.Sqrt(a * a + b * b);
        }
    }
}

这种方法是很独立的,与结构体本身没有关联,只能算逻辑上的分类

(3)逻辑运算

这里的逻辑运算包括:加、减、乘、除、大于、小于、等于、不等于等。下面以实现加法为例。

c 复制代码
    DoubleVec doubleVec1;
    DoubleVec doubleVec2;
    void Start()
    {
        doubleVec1 = new DoubleVec(1, 1, 1);
        doubleVec2 = new DoubleVec(2, 2, 2);
        DoubleVec doubleVec3 = doubleVec1 + doubleVec2;
    }

创建方法

c 复制代码
public struct DoubleVec
{
    public double x;
    public double y;
    public double z;

    //构造函数
    public DoubleVec(double x, double y, double z)
    {
        this.x = x;
        this.y = y;
        this.z = z;
    }
    //使用operator运算符重载方法
    //参数中必须有一个为DoubleVec
    public static DoubleVec operator +(DoubleVec a, DoubleVec b)
    {
        return new DoubleVec(a.x + b.x, a.y + b.y, a.z + b.z);
    }
}

(4)operator 运算符的用法

一元运算符

一个参变量,直接跟变量使用

c 复制代码
   //operator +
    public static DoubleVec operator +(DoubleVec a)
    {
        return new DoubleVec(a.x , a.y , a.z );
    }
  //operator -
    public static DoubleVec operator -(DoubleVec a)
    {
        return new DoubleVec(-a.x , -a.y , -a.z );
    }
  //operator ++
    public static DoubleVec operator ++(DoubleVec a)
    {
        return new DoubleVec(a.x+1 , a.y+1 , a.z+1 );
    }
  //operator --
    public static DoubleVec operator --(DoubleVec a)
    {
        return new DoubleVec(a.x-1 , a.y-1 , a.z-1 );
    }
  //operator !
    public static bool operator !(DoubleVec a)
    {
        return true;
    }

使用方法

c 复制代码
        doubleVec1 = new DoubleVec(1, 1, 1);
        DoubleVec doubleVec3 = - doubleVec1;//对应operator +
        doubleVec3 = +doubleVec1;//对应operator -
        doubleVec3 = doubleVec1++;//对应operator ++
        doubleVec3 = doubleVec1--;//对应operator --
        bool bo = !doubleVec1;//对应operator !

二元运算符

需要两个变量进行运算

c 复制代码
   //operator +
    public static DoubleVec operator +(DoubleVec a, DoubleVec b)
    {
        return new DoubleVec(a.x + b.x, a.y + b.y, a.z + b.z);
    }
   //也允许其中一个变量不是结构体的类型
    public static DoubleVec operator +(DoubleVec a, double b)
    {
        return new DoubleVec(a.x + b, a.y + b, a.z + b);
    }
  //operator -
    public static DoubleVec operator -(DoubleVec a, DoubleVec b)
    {
        return new DoubleVec(a.x - b.x, a.y - b.y, a.z - b.z);
    }
  //operator *
    public static DoubleVec operator *(DoubleVec a, double b)
    {
        return new DoubleVec(a.x * b, a.y * b, a.z * b);
    }
  //operator /
    public static DoubleVec operator /(DoubleVec a, double b)
    {
        return new DoubleVec(a.x / b, a.y / b, a.z / b);
    }

使用方法

c 复制代码
        doubleVec1 = new DoubleVec(1, 1, 1);
        doubleVec2 = new DoubleVec(2, 2, 2);
        DoubleVec doubleVec3 =  doubleVec1;
        doubleVec3 = doubleVec1 + doubleVec2;//对应operator +
        doubleVec3 = doubleVec1 - doubleVec2;//对应operator -
        doubleVec3 = doubleVec1 + 1;//对应operator +
        doubleVec3 = doubleVec1 * 1;//对应operator*
        doubleVec3 = doubleVec1 / 1;//对应operator/

比较运算符

两个变量进行比较

c 复制代码
  //operator == 
public static bool operator == (DoubleVec a, DoubleVec b)
    {
        if (a.x==b.x&& a.y==b.y&&a.z==b.z)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
  //operator != 
    public static bool operator !=(DoubleVec a, DoubleVec b)
    {
        if (a.x != b.x && a.y!= b.y && a.z != b.z)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
  //operator >
    public static bool operator >(DoubleVec a, DoubleVec b)
    {
        double magA = a.magnitude();
        double magB = b.magnitude();
        if (magA> magB)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
  //operator <
    public static bool operator <(DoubleVec a, DoubleVec b)
    {
        double magA = a.magnitude();
        double magB = b.magnitude();
        if (magA < magB)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
  //operator >=
    public static bool operator >= (DoubleVec a, DoubleVec b)
    {
        double magA = a.magnitude();
        double magB = b.magnitude();
        if (magA >= magB)
        {
            return true;
        }
        else
        {
            return false;
        }
    }
  //operator <=
    public static bool operator <= (DoubleVec a, DoubleVec b)
    {
        double magA = a.magnitude();
        double magB = b.magnitude();
        if (magA <= magB)
        {
            return true;
        }
        else
        {
            return false;
        }
    }

使用方法

c# 复制代码
        bool _bool = doubleVec1 == doubleVec2;
        _bool = doubleVec1 != doubleVec2;
        _bool = doubleVec1 > doubleVec2;
        _bool = doubleVec1 < doubleVec2;
        _bool = doubleVec1 <= doubleVec2;
        _bool = doubleVec1 >= doubleVec2;

4.扩展方法

扩展方法可以是对unity中的类,密封类和结构体中的方法进行扩展。也可以对自己创建的结构体和类进行扩展,不过感觉很多余。

创建没有继承的静态类

c# 复制代码
public static class LearnExtention 
{
}

添加静态扩展方法,第一个参数用this修饰,类型为需要扩展的类型,后面为需要扩展的发方法所需要的参数。

c 复制代码
///对上文的结构体进行扩展,求单位向量
public static class LearnExtention 
{
    public static DoubleVec normalized(this DoubleVec doubleVec)
    {
        return doubleVec / doubleVec.Magnitude;
    }
}

使用方法

c 复制代码
   doubleVec1 = new DoubleVec(2, 2, 2);
//在类型的变量后点出方法使用
   doubleVec2 = doubleVec1.normalized();
//因为方法为静态的,所以可以直接使用
   doubleVec2 = LearnExtention.normalized(doubleVec1);
相关推荐
异次元的归来18 分钟前
Unity DOTS中的share component
unity·游戏引擎
Dream_Snowar22 分钟前
速通Python 第三节
开发语言·python
高山我梦口香糖1 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
信号处理学渣2 小时前
matlab画图,选择性显示legend标签
开发语言·matlab
红龙创客2 小时前
某狐畅游24校招-C++开发岗笔试(单选题)
开发语言·c++
jasmine s2 小时前
Pandas
开发语言·python
biomooc2 小时前
R 语言 | 绘图的文字格式(绘制上标、下标、斜体、文字标注等)
开发语言·r语言
骇客野人2 小时前
【JAVA】JAVA接口公共返回体ResponseData封装
java·开发语言
black^sugar2 小时前
纯前端实现更新检测
开发语言·前端·javascript
404NooFound2 小时前
Python轻量级NoSQL数据库TinyDB
开发语言·python·nosql