Unity 超基础学习笔记(⼆)
Unity超基础学习笔记(⼆)
1. 基本数据类型的扩展
之前在K12中学习了⼀些基本的数据类型,实际上C#⽀持更多的数据类型。如下:
注意⽆符号整型数和有符号整型数的表⽰范围,例如:
int 能表⽰ -231-1;
uint 能表⽰ 0~2^32-1;
2. 类型转换
同种数据(例如都是整型)的不同数据类型可以互相转换。有两种⽅法。
1) 隐式类型转换 。这些转换是 C# 默认的以安全⽅式进⾏的转换, 不会导致数据丢失,也就是从表⽰范围⼩转换到表⽰范围⼤的数据。例如,从⼩的整数类型转换为⼤的整数类型,从派⽣类转换为基类。
int a =1;
long b =a ;//可以成⽴
2) 显式类型转换 ,即强制类型转换。显式转换需要强制转换运算符,⽽且强制转换会造成数据丢失,也就是从表⽰范围⼤转换到表⽰范围⼩的数据。所以在转换之前要确认不会丢失的数据,或丢失的数据是可以丢失的。
long b =1;
int a =(int )b ;
不同种数据之前也可以互相转换:
1) 本⾝⼀些类会提供数据转换的⽅法:
int a = 1;
a .ToString ();//转换成字符串
2) Convert类中提供了⼀些数据转换的⽅法:
31~2
string str = “123”;
int a = Convert.ToInt32(str);//将str转换成int类型,失败报错。
3) 在基本类型中提供了Parse和TryParse⽅法来数据转换:
string str = “123”;
int a =int.Parse(str);//将str转换成int类型,失败报错。
4) Convert和Parse的转换区别:
(1) 这两个⽅法的最⼤不同是它们对 null 值的处理⽅法: Convert.ToInt32(null) 会返回 0 ⽽不会产⽣任何异常,但 int.Parse(null) 则会产⽣异常。
(2) 对数据进⾏四舍五⼊时候的区别 :
a. Convert.ToInt32(double value) 如果 value 为两个整数中间的数字,则返回⼆者中的偶数;即 3.5 转换为 4,4.5 转换为 4,⽽ 5.5转换为 6。不过 4.6 可以转换为 5,4.4 转换为 4 。
b. int.Parse(“4.5”) 直接报错:“输⼊字符串的格式不正确”。
c. int(4.6) = 4 Int 转化其他数值类型为 Int 时没有四舍五⼊,强制转换。
(3) 对被转换类型的区别 int.Parse 是转换 String 为 int, Convert.ToInt32 是转换继承⾃ Object 的对象为 int 的(可以有很多其它类型的数据)。你得到⼀个 object 对象, 你想把它转换为 int, ⽤ int.Parse 就不可以, 要⽤ Convert.ToInt32。
3. (is关键字)检查表达式是否为指定类型:
a is int;//变量 is 数据类型或者类名;
//判断变量是否为该数据类型或者类,是的话为返回True,否的话返回False
4. 变量的作⽤域:
在C#中声明的变量是有使⽤范围的。例如在unity脚本中:
public class NewBehaviourScript : MonoBehaviour
{
int a;//可以在start⽅法和Update⽅法中使⽤
// Start is called before the first frame update
void Start()
switch语句表示范围{
int b;//只可以在start⽅法中使⽤
}
// Update is called once per frame
void Update()
{
}
}
5. 常量:
对于⼀些不会改变的数据,可以将其声明为⼀个常量。例如圆周率可以声明为PI。
const float PI=3.14f;//声明常量
//PI=11;//常量不可修改该句会编译错误。
6. Switch语句
例如有个需求是当level=1时,执⾏FuncA();当level=2时,执⾏FuncB();当level=3时,执⾏FuncC()。⽽level只有这个三种情况下,⽤if 条件句表⽰如下:
int level =1;
if(level ==1)
FuncA();
else if(level ==2)
FuncB();
else if(level ==3)
FuncC();
显然这样有点难以阅读,这时就可以引⼊switch语句。
switch(level)
{
case1:
FuncA();
break;
case2:
FuncB();
break;
case3:
FuncC();
break;
default://可选
Debug.Log(“ERROR”);
break;
}
这样程序会根据level的值来选择要执⾏的语句。显然为了⼀⼀对应,level这⾥的变量,必须是整型或者枚举型,或者可以转换成整型或者枚举型的变量。⽽case 后接的数必须是个常量,不能是变量。原则上每个case语句后头都要跟⼀个break;,但如果该case语句为空时,可以不接break;,程序将直接执⾏下⼀条case的语句直⾄遇到break;例如:
int level =1;
switch(level)
{
case1:
case2:
Debug.Log(“2”);
break;
}
这时会输出2。
7. 再论循环
1. 在多重循环中,最长的循环应放在最内层,在允许的情况下最短的循环应放在最外层以减少CPU跨切循环层的次数。
int[,] a=new int[6,2];
for(int i=0;i<2;i++)
{
for(int j=0;j<6;j++)
{
a[j,i]=i+j;
}
}
2. 建议for循环中循环控制变量的取值采⽤半开半闭写法。
int[] a=new int[6];
for(int i=0;j<6;i++)//[0,6)区间
//不⽤for(int i=0;j<=5;i++) [0,5]区间
{
a[i]=i;
}
8. 在unity中使⽤循环(关于协程)
通常有⼀个需求,例如我在unity的脚本⾥写了⼀个循环输出1,2,3……但我不希望他⼀下⼦输出出来。⽽是每隔⼏秒后输出,形成⼀个动画。如下,如果我直接将循环写在start⽅法⾥,它就会⼀下⼦输出出来,不能完成我的需求。因为根据unity的运⾏顺序,要等所有的start⽅法和update⽅法都运⾏完后才会渲染画⾯,之后到下⼀帧。
void Start()
{
for(int i =0; i <10; i++)
{
Debug.Log(i);
}
}
这时候就需要⽤到协程。则将以上程序改下如下:
void Start()
{
StartCoroutine(Show());//开启协程
}
IEnumerator Show()//协程⽅法的写法,返回是迭代器
{
for(int i =0; i <10; i++)
{
Debug.Log(i);
yield return new WaitForSeconds(0.5f);//代码在这中断,直⾄0.5秒过后的下⼀帧重新回到该处运⾏下⼀条代码,也就是下⼀次for循环。
}
}
9. 再论⽅法的参数:
之前我们在C#基础中学习了⽤值类型(如int)和引⽤类型(如int[])作为参数的不同。这次我们讨论另外三种情况:
1) 我们就是想传⼀个值类型参数进去,让⽅法内能直接修改该参数的值。
这时我们就要⽤到ref关键字,把ref加在形参类型之前就⾏。在调⽤的时候,同样要把ref加在实参的前⾯。
class Program
{
static void Main(string[] args)
{
int x =1;
Func(ref x);
Console.WriteLine(x);
}
static void Func(ref int a)
{
a =2;
}
}
那考虑⼀个问题,对于引⽤类型的参数,ref是不是没有意义了。那我们看下这个例⼦:
class Program
{
static void Main(string[] args)
{
int[] x ={1,2,3,4};
Func(x);
Console.WriteLine(x[0]);
}
static void Func(int[] a)
{
a =new int[]{5,6,7,8};
}
}
考虑输出的是⼏?明显还是1。因为形参只是复制了⼀份引⽤地址,当在⽅法内改变形参的引⽤地址时,外部的实参还是不受影响的。
这时给形参和实参加上ref的话:
class Program
{
static void Main(string[] args)
{
int[] x ={1,2,3,4};
Func(ref x);
Console.WriteLine(x[0]);
}
static void Func(ref int[] a)
{
a =new int[]{5,6,7,8};
}
}
2) 想传回更多的值:
这时可以⽤out关键字,类似ref,也是按引⽤传递。与ref关键字的区别在于ref需要在实参在传进去的时候⼀定要初始化过(如int x=1;//要赋个值),⽽out不要求传⼊前赋值,但要求传出时要赋值。
static void Main(string[] args)
{
int x ;
Func(out x);
Console.WriteLine(x);
}
static void Func(out int a)
{
a =2;
}
3) 不知道要传⼏个值进去:
例如要累加⼏个数,但具体数⽬不知道。除了⽤数组来传之外还可以⽤params这个关键字。如下:
static void Main(string[] args)
{
int x=1;
int y=2;
int z=3;
Console.WriteLine(Func(x,y,z));
}
static int Func(params int[] a)
{
int sum =0;
for(int i =0; i < a.Length; i++)
{
sum += a[i];
}
return sum;
}
可见params 是将参数复制在⼀个⼀维数组之中来传递(因此params声明后边必须跟的是⼀维数组)。那么思考是否能传⼀个⼀维数组进去呢?结论是可以的。那么这时是算传引⽤类型参数吗?
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论