【C#基础】unity中结构体的使用
结构体(Struct)是值类型数据结构,在栈上分配内存,可以包含字段,属性,方法,构造函数。结构体可以实现接口,但是不能继承。在Dots里有大量依靠Struct实现接口来定义Entities数据类型和实现逻辑。
一、结构体的基本使用
- 定义结构体
- 结构体初始化
- 结构体方法
- 结构体扩展方法
1.定义结构体
结构体一般用于小型的数据类型,下面定义一个双精度的三维坐标数据为例。
Public struct DoubleVec {}
2.结构体初始化
(1)通常通过构造函数对结构体进行初始化,也可以单独定义后赋值。
结构体
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;}
}
初始化和单独赋值
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);}
结果
doubleVec1.x=1
doubleVec2.x=3
(2)没有对结构体进行初始化或者赋值,直接调用结构体的字段
重新定义一个字段类型多的结构体
public struct DoubleVec
{public float x;public float y;public double z;public string name;public Vector3 vec;public bool bo;public int[] ints;
}
直接使用字段
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);}
结果
doubleVec2.y=0 //浮点类型初始为0doubleVec2.vec=(0.00, 0.00, 0.00)//vecter初始为原点doubleVec2.name= //字符串为空doubleVec2.ints= //数组为空doubleVec2.bo=False //bool为falsedoubleVec2.x=0
(3)构造函数
实例构造函数:初始化字段信息,构造函数参数必须对没有字段进行赋值
静态构造函数:当结构体构造实例时,静态构造函数会自动调用一次;不带任何参数,不带修饰符。
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方法
可以直接在结构体变量后使用,下面以求模长为例
DoubleVec doubleVec1;void Start(){doubleVec1 = new DoubleVec(1, 1, 1);//这里直接可以点出方法double mag= doubleVec1.Magnitude;Debug.Log("mag=" + mag);}
创建的方法
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)结构体传参方法
可以在结构类型后面点出方法,传入参数进行逻辑处理,同样以求模长为例
DoubleVec doubleVec1;void Start(){doubleVec1 = new DoubleVec(1, 1, 1);//这里是同结构体类型点出方法,参数为结构体变量double mag= DoubleVec.MagnitudeVec(doubleVec1);Debug.Log("mag=" + mag);}
创建方法
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)逻辑运算
这里的逻辑运算包括:加、减、乘、除、大于、小于、等于、不等于等。下面以实现加法为例。
DoubleVec doubleVec1;DoubleVec doubleVec2;void Start(){doubleVec1 = new DoubleVec(1, 1, 1);doubleVec2 = new DoubleVec(2, 2, 2);DoubleVec doubleVec3 = doubleVec1 + doubleVec2;}
创建方法
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运算符重载方法//参数中必须有一个为DoubleVecpublic static DoubleVec operator +(DoubleVec a, DoubleVec b){return new DoubleVec(a.x + b.x, a.y + b.y, a.z + b.z);}
}
(4)operator 运算符的用法
一元运算符
一个参变量,直接跟变量使用
//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;}
使用方法
doubleVec1 = new DoubleVec(1, 1, 1);DoubleVec doubleVec3 = - doubleVec1;//对应operator +doubleVec3 = +doubleVec1;//对应operator -doubleVec3 = doubleVec1++;//对应operator ++doubleVec3 = doubleVec1--;//对应operator --bool bo = !doubleVec1;//对应operator !
二元运算符
需要两个变量进行运算
//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);}
使用方法
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/
比较运算符
两个变量进行比较
//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;}}
使用方法
bool _bool = doubleVec1 == doubleVec2;_bool = doubleVec1 != doubleVec2;_bool = doubleVec1 > doubleVec2;_bool = doubleVec1 < doubleVec2;_bool = doubleVec1 <= doubleVec2;_bool = doubleVec1 >= doubleVec2;
4.扩展方法
扩展方法可以是对unity中的类,密封类和结构体中的方法进行扩展。也可以对自己创建的结构体和类进行扩展,不过感觉很多余。
创建没有继承的静态类
public static class LearnExtention
{
}
添加静态扩展方法,第一个参数用this修饰,类型为需要扩展的类型,后面为需要扩展的发方法所需要的参数。
///对上文的结构体进行扩展,求单位向量
public static class LearnExtention
{public static DoubleVec normalized(this DoubleVec doubleVec){return doubleVec / doubleVec.Magnitude;}
}
使用方法
doubleVec1 = new DoubleVec(2, 2, 2);
//在类型的变量后点出方法使用doubleVec2 = doubleVec1.normalized();
//因为方法为静态的,所以可以直接使用doubleVec2 = LearnExtention.normalized(doubleVec1);