C#Unity3D中的C#编程初级

Posted 恬静的小魔龙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#Unity3D中的C#编程初级相关的知识,希望对你有一定的参考价值。

推荐阅读

大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。

一、前言

这篇文章主要是给零基础想要Unity入门的关于C#编程的一些意见

二、参考文章

unity中的C#编程-零基础(Unity2017)

三、正文

1、支持Unity3D的编程语言

  • C#、javascript、UnityScript
    先说C#与JavaScript,因为JavaScript是动态的,肯定不如编译的C#好,但是JavaScript更快捷一点, JavaScript适合个人开发,敏捷快速。c#适合公司开发,规范严谨。
  • 然后说说这个C#和Unity内置的UnityScript
    UnityScript脱胎于.Net平台的第三方语言Boo,差距可能是全方位,立体式的。社区支持,代码维护,甚至是编译出来的CIL代码质量都可能有很大的差距。另外从Unity5.0版本开始就会停止对Boo的文档支持。同时消失的还有从菜单创建Boo脚本的选项“Create Boo Script”。从U3D团队对Boo的态度,也可以窥见和Boo联系密切的UnityScript未来的走势。

2、编程工具(IDE)

  • Visual Studio 全系列
  • Visual Studio Code
  • Xamarin Studio
    这个主要是在Mac上使用的IDE,因为在Mac上不能使用VS,MonoDevelop也不能输入中文,就挺难受的,就可以使用XamarinStudio,关于这个IDE使用可以参考这篇文章。http://www.xuanyusong.com/archives/3545
  • MonoDevelop
    Unity3D内置的编辑器,操作感觉一般,但是胜在方便,在安装Unity3D的时候就可以一起安装了,不用另外安装IDE了
  • JetBrains Rider
    一款强大的强大的跨平台C#编辑器,官网https://www.jetbrains.com/zh/dotnet/promo/unity/

3、创建C#代码

  1. 在工程目录下右键点击,选择Create->C# Script
  2. 在任意对象上,点击Add Component->New Script

    这个是创建成功后的初始脚本的样子

4、场景的保存和脚本的保存

  • 快捷键F2 点击场景名或者脚本名字可以重命名
  • 快捷键Ctrl+S 快速保存场景或者保存脚本
  • 状态栏中显示“*”号的都是未保存的
  • 编辑器意外奔溃,场景未来得及保存?
    这时可以打开工程目录,找到/Temp/_Backupscenes/文件夹,可以看到有后缀名为.backup的文件,将该文件的后缀名改为.unity拖拽到项目视图,即可还原编辑器崩溃前的场景。

5、关于日志输出(指控制输出,其中Log有三类:正常、警告、错误输出)

  • print
    是MonoBehaviour的一个成员,必须继承MonoBehaviour才能使用,通过反编译可以看到print的方法为
public static void print(object message)

	Debug.Log(message);

说明print方法还是通过Debug.Log实现的,print就是Debug.Log的一个简单封装。

  • Debug.Log
    输出log信息,可以在运行的时候查看关键数据的变化

  • Debug.LogWarning
    输出警告信息

  • Debug.LogError
    输出错误信息


6、变量与常量

因为两个比较相似,就放一块说

  • 变量
    一个变量只不过是一个供程序操作的存储区的名字。在 C# 中,每个变量都有一个特定的类型,类型决定了变量的内存大小和布局。范围内的值可以存储在内存中,可以对变量进行一系列操作。

  • 常量
    常量是固定值,程序执行期间不会改变。常量可以是任何基本数据类型,比如整数常量、浮点常量、字符常量或者字符串常量,还有枚举常量。
    常量可以被当作常规的变量,只是它们的值在定义后不能被修改。

  • 变量的类型

类型 举例
整数类型 sbyte、byte、short、ushort、int、uint、long、ulong 和 char
浮点型 float 和 double
十进制类型 decimal
布尔类型 true 或 false 值,指定的值
空类型 可为空值的数据类型
其他变量类型 枚举enum,引用类型变量class,结构体类型struct
- 变量的定义
int i, j, k;
char c, ch;
float f, salary;
double d;
  • 变量的初始化
int d = 3, f = 5;    /* 初始化 d 和 f. */
byte z = 22;         /* 初始化 z. */
double pi = 3.14159; /* 声明 pi 的近似值 */
char x = 'x';        /* 变量 x 的值为 'x' */

实例

namespace VariableDefinition

    class Program
    
        static void Main(string[] args)
        
            short a;
            int b ;
            double c;

            /* 实际初始化 */
            a = 10;
            b = 20;
            c = a + b;
            Console.WriteLine("a = 0, b = 1, c = 2", a, b, c);
            Console.ReadLine();
        
    

编译执行结果:

a = 10, b = 20, c = 30
  • 常量的定义
 const double pi = 3.14159; // 常量声明
  • 常量的类型
整数常量

整数常量可以是十进制、八进制或十六进制的常量。前缀指定基数:0x 或 0X 表示十六进制,0 表示八进制,没有前缀则表示十进制。

整数常量也可以有后缀,可以是 U 和 L 的组合,其中,U 和 L 分别表示 unsigned 和 long。后缀可以是大写或者小写,多个后缀以任意顺序进行组合。

212         /* 合法 */
215u        /* 合法 */
0xFeeL      /* 合法 */
078         /* 非法:8 不是一个八进制数字 */
032UU       /* 非法:不能重复后缀 */
85         /* 十进制 */
0213       /* 八进制 */
0x4b       /* 十六进制 */
30         /* int */
30u        /* 无符号 int */
30l        /* long */
30ul       /* 无符号 long */
浮点常量

一个浮点常量是由整数部分、小数点、小数部分和指数部分组成。您可以使用小数形式或者指数形式来表示浮点常量。
这里有一些浮点常量的实例:

3.14159       /* 合法 */
314159E-5L    /* 合法 */
510E          /* 非法:不完全指数 */
210f          /* 非法:没有小数或指数 */
.e55          /* 非法:缺少整数或小数 */

使用小数形式表示时,必须包含小数点、指数或同时包含两者。使用指数形式表示时,必须包含整数部分、小数部分或同时包含两者。有符号的指数是用 e 或 E 表示的。

字符常量

字符常量是括在单引号里,例如,‘x’,且可存储在一个简单的字符类型变量中。一个字符常量可以是一个普通字符(例如 ‘x’)、一个转义序列(例如 ‘\\t’)或者一个通用字符(例如 ‘\\u02C0’)。

在 C# 中有一些特定的字符,当它们的前面带有反斜杠时有特殊的意义,可用于表示换行符(\\n)或制表符 tab(\\t)。在这里,列出一些转义序列码:

转义序列含义
\\\\\\ 字符
\\'' 字符
\\"" 字符
\\?? 字符
\\aAlert 或 bell
\\b退格键(Backspace)
\\f换页符(Form feed)
\\n换行符(Newline)
\\r回车
\\t水平制表符 tab
\\v垂直制表符 tab
\\ooo一到三位的八进制数
\\xhh . . .一个或多个数字的十六进制数
实例:
namespace EscapeChar

    class Program
    
        static void Main(string[] args)
        
            Console.WriteLine("Hello\\tWorld\\n\\n");
            Console.ReadLine();
        
    

编译执行结果:

Hello   World
字符串常量

字符串常量是括在双引号 “” 里,或者是括在 @"" 里。字符串常量包含的字符与字符常量相似,可以是:普通字符、转义序列和通用字符

使用字符串常量时,可以把一个很长的行拆成多个行,可以使用空格分隔各个部分。

这里是一些字符串常量的实例。下面所列的各种形式表示相同的字符串。

string a = "hello, world";                  // hello, world
string b = @"hello, world";               // hello, world
string c = "hello \\t world";               // hello     world
string d = @"hello \\t world";               // hello \\t world
string e = "Joe said \\"Hello\\" to me";      // Joe said "Hello" to me
string f = @"Joe said ""Hello"" to me";   // Joe said "Hello" to me
string g = "\\\\\\\\server\\\\share\\\\file.txt";   // \\\\server\\share\\file.txt
string h = @"\\\\server\\share\\file.txt";      // \\\\server\\share\\file.txt
string i = "one\\r\\ntwo\\r\\nthree";
string j = @"one
two
three";

实例:

using System;

namespace DeclaringConstants

    class Program
    
        static void Main(string[] args)
        
            const double pi = 3.14159; // 常量声明
            double r;
            Console.WriteLine("Enter Radius: ");
            r = Convert.ToDouble(Console.ReadLine());
            double areaCircle = pi * r * r;
            Console.WriteLine("Radius: 0, Area: 1", r, areaCircle);
            Console.ReadLine();
        
    

编译执行结果:

Enter Radius: 
3
Radius: 3, Area: 28.27431

7、方法的定义和调用

  • 方法的定义
    语法如下:
<Access Specifier> <Return Type> <Method Name>(Parameter List)

   Method Body

下面是方法的各个元素:

  • Access Specifier:访问修饰符,这个决定了变量或方法对于另一个类的可见性。
  • Return type:返回类型,一个方法可以返回一个值。返回类型是方法返回的值的数据类型。如果方法不返回任何值,则返回类型为 void
  • Method name:方法名称,是一个唯一的标识符,且是大小写敏感的。它不能与类中声明的其他标识符相同。
  • Parameter list:参数列表,使用圆括号括起来,该参数是用来传递和接收方法的数据。参数列表是指方法的参数类型、顺序和数量。参数是可选的,也就是说,一个方法可能不包含参数。
  • Method body:方法主体,包含了完成任务所需的指令集。
实例: 下面的代码片段显示一个函数 FindMax,它接受两个整数值,并返回两个中的较大值。它有 public 访问修饰符,所以它可以使用类的实例从类的外部进行访问。
class NumberManipulator

   public int FindMax(int num1, int num2)
   
      /* 局部变量声明 */
      int result;

      if (num1 > num2)
         result = num1;
      else
         result = num2;

      return result;
   
   ...

  • 方法的调用
using System;

namespace CalculatorApplication

   class NumberManipulator
   
      public int FindMax(int num1, int num2)
      
         /* 局部变量声明 */
         int result;

         if (num1 > num2)
            result = num1;
         else
            result = num2;

         return result;
      
      static void Main(string[] args)
      
         /* 局部变量定义 */
         int a = 100;
         int b = 200;
         int ret;
         NumberManipulator n = new NumberManipulator();

         //调用 FindMax 方法
         ret = n.FindMax(a, b);
         Console.WriteLine("最大值是: 0", ret );
         Console.ReadLine();
      
   

编译执行后的结果:

最大值是: 200

您也可以使用类的实例从另一个类中调用其他类的公有方法。例如,方法 FindMax 属于 NumberManipulator 类,您可以从另一个类 Test 中调用它。

using System;

namespace CalculatorApplication

    class NumberManipulator
    
        public int FindMax(int num1, int num2)
        
            /* 局部变量声明 */
            int result;

            if (num1 > num2)
                result = num1;
            else
                result = num2;

            return result;
        
    
    class Test
    
        static void Main(string[] args)
        
            /* 局部变量定义 */
            int a = 100;
            int b = 200;
            int ret;
            NumberManipulator n = new NumberManipulator();
            //调用 FindMax 方法
            ret = n.FindMax(a, b);
            Console.WriteLine("最大值是: 0", ret );
            Console.ReadLine();

        
    

编译执行的结果:

最大值是: 200
  • 递归方法的调用
    一个方法可以自我调用。这就是所谓的 递归。下面的实例使用递归函数计算一个数的阶乘:
using System;

namespace CalculatorApplication

    class NumberManipulator
    
        public int factorial(int num)
        
            /* 局部变量定义 */
            int result;

            if (num == 1)
            
                return 1;
            
            else
            
                result = factorial(num - 1) * num;
                return result;
            
        
    
        static void Main(string[] args)
        
            NumberManipulator n = new NumberManipulator();
            //调用 factorial 方法
            Console.WriteLine("6 的阶乘是: 0", n.factorial(6));
            Console.WriteLine("7 的阶乘是: 0", n.factorial(7));
            Console.WriteLine("8 的阶乘是: 0", n.factorial(8));
            Console.ReadLine();

        
    

编译执行后的结果:

6 的阶乘是: 720
7 的阶乘是: 5040
8 的阶乘是: 40320
  • 参数传递
    当调用带有参数的方法时,您需要向方法传递参数。在 C# 中,有三种向方法传递参数的方式:
方式描述
值参数这种方式复制参数的实际值给函数的形式参数,实参和形参使用的是两个不同内存中的值。在这种情况下,当形参的值发生改变时,不会影响实参的值,从而保证了实参数据的安全。
引用参数这种方式复制参数的内存位置的引用给形式参数。这意味着,当形参的值发生改变时,同时也改变实参的值。
输出参数这种方式可以返回多个值。
- 按值参数传递

这是参数传递的默认方式。在这种方式下,当调用一个方法时,会为每个值参数创建一个新的存储位置。
实际参数的值会复制给形参,实参和形参使用的是两个不同内存中的值。所以,当形参的值发生改变时,不会影响实参的值,从而保证了实参数据的安全。下面的实例演示了这个概念:

using System;
namespace CalculatorApplication

   class NumberManipulator
   
      public void swap(int x, int y)
      
         int temp;
         
         temp = x; /* 保存 x 的值 */
         x = y;    /* 把 y 赋值给 x */
         y = temp; /* 把 temp 赋值给 y */
      
      
      static void Main(string[] args)
      
         NumberManipulator n = new NumberManipulator();
         /* 局部变量定义 */
         int a = 100;
         int b = 200;
         
         Console.WriteLine("在交换之前,a 的值: 0", a);
         Console.WriteLine("在交换之前,b 的值: 0", b);
         
         /* 调用函数来交换值 */
         n.swap(a, b);
         
         Console.WriteLine("在交换之后,a 的值: 0", a);
         Console.WriteLine("在交换之后,b 的值: 0", b);
         
         Console.ReadLine();
      
   

编译执行后的结果:

在交换之前,a 的值:100
在交换之前,b 的值:200
在交换之后,a 的值:200
在交换之后,b 的值:100

结果表明,swap 函数内的值改变了,且这个改变可以在 Main 函数中反映出来。

  • 按输出传递参数

return 语句可用于只从函数中返回一个值。但是,可以使用 输出参数 来从函数中返回两个值。输出参数会把方法输出的数据赋给自己,其他方面与引用参数相似。

下面的实例演示了这点:

using System;

namespace CalculatorApplication

   class NumberManipulator
   
      public void getValue(out int x )
      
         int temp = 5;
         x = temp;
      
   
      static void Main(string[] args)
      
         NumberManipulator n = new NumberManipulator();
         /* 局部变量定义 */
         int a = 100;
         
         Console.WriteLine("在方法调用之前,a 的值: 0", a);
         
         /* 调用函数来获取值 */
         n.getValue(out a);

         Console.WriteLine("在方法调用之后,a 的值: 0", a);
         Console.ReadLine();

      
   

编译执行后的结果:

在方法调用之前,a 的值: 100
在方法调用之后,a 的值: 5

提供给输出参数的变量不需要赋值。当需要从一个参数没有指定初始值的方法中返回值时,输出参数特别有用。请看下面的实例,来理解这一点

using System;

namespace CalculatorApplication

   class NumberManipulator
   
      public void getValues(out int x, out int y )
      
          Console.WriteLine("请输入第一个值: ");
          x = Convert.ToInt32(Console.ReadLine());
          Console.WriteLine("请输入第二个值: ");
          y = Convert.ToInt32(Console.ReadLine());
      
   
      static void Main(string[] args)
      
         NumberManipulator n = new NumberManipulator();
         /* 局部变量定义 */
         int a , b;
         
         /* 调用函数来获取值 */
         n.getValues(out a, out b);

         Console.WriteLine("在方法调用之后,a 的值: 0", a);
         Console.WriteLine("在方法调用之后,b 的值: 0", b);
         Console.ReadLine();
      
   

编译执行后的结果:

请输入第一个值:
7
请输入第二个值:
8
在方法调用之后,a 的值: 7
在方法调用之后,b 的值: 8

8、方法中的参数,返回值

  • 方法中参数的类型有三种
int型参数

int 型参数通过值传递的方式将数值传入方法中,即我们在Java中常见的方法。

ref型参数

该种类型的参数传递变量地址给方法(引用传递),传递前变量必须初始化。

该类型与out型的区别在与:

1).ref 型传递变量前,变量必须初始化,否则编译器会报错, 而 out 型则不需要初始化
2).ref 型传递变量,数值可以传入方法中,而 out 型无法将数据传入方法中。换而言之,ref 型有进有出,out 型只出不进。

out 型参数

与 ref 型类似,仅用于传回结果。

注意:

1). out型数据在方法中必须要赋值,否则编译器会报错。

eg:如下图若将代码中的sum1方法的方法体

改为 a+=b; 则编译器会报错。原因:out 型只出不进,在没给 a 赋值前是不能使用的

改为 b+=b+2; 编译器也会报错。原因:out 型数据在方法中必须要赋值。

2). 重载方法时若两个方法的区别仅限于一个参数类型为ref 另一个方法中为out,编译器会报错

eg:若将下面的代码中将方法名 vsum1 改为 sum(或者将方法名 sum 改为 sum1),编译器会报错。

Error 1 Cannot define overloaded method ‘sum’ because it differs from another method only on ref and out

原因:参数类型区别仅限于 为 ref 与为 out 时,若重载对编译器而言两者的元数据表示完全相同。

class C

    //1. in型参数
    public void sum(int a, int b) 
        a += b;
    
    //2. ref型参数
    public void sum(ref int a, int b)
    
        a +=以上是关于C#Unity3D中的C#编程初级的主要内容,如果未能解决你的问题,请参考以下文章

unity3d c#支持热更吗

Unity3D 学习路线?

Unity3D游戏开发之C#编程中常见数据结构的比较

C#中的委托是啥?事件是否一种委托?

C#中的委托是啥?事件是否一种委托?

Unity3D中的单例模式