首页 > 编程语言 >C#与unity学习

C#与unity学习

时间:2022-10-18 23:36:19浏览次数:63  
标签:float C# void Vector3 transform 学习 unity 坐标 public

C#与unity学习

unity中产创建c#文件

在unity中新建project,为方便管理可以在assets文件内创建scripts文件夹,将所有的c#文件集中在此文件夹中管理。

在vsstudio中创建c#

image-20220313212703957

​ 前两种都是带窗口的c#应用程序,但在实际中感觉不出来,后两仅仅指示控制台程序。

c#的四个安全级别

public:对任何脚本开放
private:变量尽在创建它们的类中可用。没有使用访问修饰符声明的任何变量默认都是私有的。
protected:变量在所属类和派生类中可以访问。
internal:仅在当前程序集中可用。

打开wpf应用(全称windows platform formdation

c#源文件中要当心类名和文件名不一致问题

初始类与命名空间与类库

namespace:

以树形结构的形式管理各个数据结构和类以及其他命名空间

class:

与c++中的十分相似。

在c#中所有的函数引用或者类的引用都是调用命名空间来是实现。

例如:

using System
using System.io

仅使用Sytem的命名空间时,不能在没用生命IO命名空间的情况下直接访问System内的io命名空间内的类

path() //这是不行的。
io.ptah()//这样就可以了

类库

程序想要使用类名和命名空间必须要引用相应的类库,类库是类名和命名空间能够被程序调用的基础,而类库一般是在dll文件中实现的。在程序代码中不需要显示调用类库的代码(像调用其他命名空间一样),一般vsstdio会自动识别相应的类库,且可以通过每个解决方案内的reference查看。

image-20220314140617441

如何添加自己需要的类库:

1‘)DLL引用:

​ 黑引用,无源代码,一般实在引用别人编译好了的dll文件。

在vsstdio中使用:

第一步:在solut栏内右击reference

第二部:点击browse,进入浏览文件窗口。

第三步:选择你想要引用的dll类文件

2)项目引用:

白盒子引用,源代码

在一个solution中同时船舰两个project,其中一个是类库,另一个则是需要引用该类库的项目,在需要应用类库的项目里的reference中按如下添加dll。

image-20220314142421177

类与对象

​ 对象是类的实例化

​ 在c#中使用new操作符来为类创建实例

class forrm{
    static void Main(string[] args){
		forrm myform = new forrm;	
    }
}

c#类中的三大成员:属性、方法以及事件

​ 事件是类或者对象痛着其他类或对象的机制,为c#独有

c#的数据类型

bool
sbyte :有符号为八位整数
byte:无符号为八位整数
ushot;两个字节
uint:四个字节
char:16位字符类型,与其他语言有所区别
float:32位浮点数
double:双精度浮点数 在申明浮点数的时候默认是双精度的,要申明单精度需要在每个常量后面加f.

枚举类型和结构体:

​ 枚举
enum 枚举名{枚举值1,枚举值2....},在语法上等同于结构体

enum euipment = {bodyArmor,Helmet}
euipment myquip = equipment.bodyAemor;
euipment myquip1 = (equipment)1;

枚举类型和整数类型可以相互转换。

结构体:

Struct 结构体名{

属性值;

属性值;

}

与c++中不同的地方是调用构造函数的时候必须要用到new。其他情况类似,比如对类的实例话化。

类里面的独有的属性访问器SET和GET

C#中的get和set访问器可用来获取和设置类中字段(即属性)的值,通过get和set访问器提供访问接口,从而可以避免对字段的直接访问造成的不安全性。

方法1

public 数据类型 属性名
{
    get
    {
        return 字段名;
    }
    set
    {
        字段名 = value;
    }
}

get{},get访问器用于获取类中字段的值,需要在get语句中使用return返回一个和字段类型相匹配的值。若希望该属性为只写属性,则在属性的定义中省略get()访问器。
set{},set访问器用于设置类中字段的值,将程序中传给属性的值赋值给字段。若希望该属性问只读属性,则在属性的定义中省略set()访问器。方法2使用get和set访问器:

方法2:
可以再如上代码重看到方法1的用法代码大量重复,因此C#中将属性的设置也可以简化为:

public 数据类型 属性名{ get; set; }

使用方法2定义属性时无需先定义字段,响当于C#中会自动生成一个和属性名相对应的私有字段,这个私有字段对任何类成员都不开放,只能通过定义的属性进行访问,这种属性的定义方式也成为自动属性设置。

get{},get访问器在自动属性中不能省略,若需要设置为只写属性则需在get前加private进行声明。
set{},set访问器在自动属性中可以省略,省略后表示该属性为只读属性

c#特殊循环结构foreach

foreach(datatype object in arraytest/collection)
{
    Console.WriteLine("{0} {1} {2}",name, sex, age);
}

有点类似于python里的for循环或者c++中的:使用

值类型和引用类型

传引用参数

public int Add(ref int a,int b)

其中的ref就是标定该函数形参时引用类型。

引用类型仅仅只在栈上占用一个指针的内存,其余都部署在托管堆上,就像类与数组一样还有基于object的一些类型,而值类型全部内存都部署在栈上。

类的成员

常量

与类关联的常量值

字段

相当于C++的成员变量

特性(properties)

就是属性访问器get和set,作用有三:
1.用于隐藏类成员或组件
2.用于对字段的约束,比如只能读或者只能写
3.用于响应字段变更之后的操作。

方法

类中可执行计算和操作

属性(attribute)

与读写类的命名属性相关的操作:用中括号括起来,可用于修饰类,函数以及以他关键子类型,相当于定义了新的修饰符,作用时相当于对该类型进行说明修饰,主要用于测试阶段,

​ 使用时所需要三个注意事项:

  • attribute的实例化不是通过new加构造函数实现,而是用中括号加构造函数
  • 因为中括号空间有限, 不能先实例化在给对象字段赋值,而是统一在构造函数的小括号内赋值,可以不属于构造函数的参数,也可以不定义,会有默认值
  • 构造函数的参数一定要写全

索引器

与以数组方式索引类的实例相关联的操作

事件

可由类生成的通知

运算符

类所支持的转换和表达式运算符

构造函数

析构函数

类型

类中声明的其他类型比如:
类:class(派生于System.Object);

接口:interface(接口不是一个“东西”,所以不存在派生于何处的问题Anders在《C# ProgrammingLanguage》中说,接口只是表示一种约定[contract]);
有点类似于c++中的虚基类,接口里面定义的方法必须要在派生类中得到实现,去c++虚基类不同的是,接口不能实例化,且接口捏的函数名必须透明,调用的时候是根据派生类实例化俩调用

委托:delegate(派生于System.Delegate)

​ 是函数指针的升级版:

image-20220314212601905

Action委托与 Func委托

Action action = new Action(function);
action();//间接调用function
action.invoke();//与上一行一样
Func<int,int,int> func1= new Func<int,int,int>(function);
func1();
func1.invoke();

自定义委托

public delegate double Calc(double x,double y);
Calc calc1 = new Calc(function);

委托的两种使用方式:
第一种;模板方法的使用
将一个委托作为一个模板方法的参数,则可以是的模板方法动态绑定任意函数

第二种:
回调方法调用指定的外部方法
常用与流水线模式,代码末尾,委托无返回值的情况。

object(System.Object的别名);

字符串:string(System.String的别名)

事件

委托类型字段和事件的不同之处,

通常事件的发生都会产生发送发和接收方,发送方指的是引发事件的对象,而接收方指就是获取、处理事件。成立事件时,事件与委托通常都是一起使用的,事件也称为一种特殊的委托,但他们的作用一般也不相同,用法也不同。

访问修饰符  event  委托名  事件名 ;

从上方实例化例语法可以看出,触发事件的就是发送方,而处理事件的接收方就是接收方。
【实例 1】通过事件完成在控制台上输岀“Hello Event!”的操作。

class Program
{
    //定义委托
    public delegate void SayDelegate();
    //定义事件
    public event SayDelegate SayEvent;
    //定义委托中调用的方法
    public void SayHello()
    {
        Console.WriteLine("Hello Event!");
    }
    //创建触发事件的方法
    public void SayEventTrigger()
    {
        //触发事件,必须与事件是同名方法
        SayEvent();
    }
    static void Main(string[] args)
    {
        //创建Program类的实例
        Program program = new Program();
        //实例化事件,使用委托指向处理方法
        program.SayEvent = new SayDelegate(program.SayHello);
        //调用触发事件的方法
        program.SayEventTrigger();
    }
}
//在控制台会输出HELLO,world!

unity

unity常识介绍

移动视角快捷键:
alt + 鼠标左键

调整图层:
直接在inspector栏内的order in layer 中调整。

image-20220315224328917

unity脚本组件

一般使用c#脚本自定义gameoObject的逻辑行为。在unity中创建的脚本文件内的所有类都继承于Monobehavier类,这个基类自带两个方法start()以及update(),


public class NewBehaviourScript : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

Start方法用于初始化游戏目标的属性,尽在游侠开始的时候才被调用
而Update用于更新下一帧的动作,unity 通过updtae渲染游戏画面,Update会不断地被重复执行知道游戏结束

image-20220316114136470

gameobject的视角移动

实现方式:右健gameobject

  1. Move to view :强制将该gameobject位置 移动Scene中央位置,不是Game视图下也就是Main camera 的中央位置
  2. alligen viwe with selected:将Scene的视角移动到右击的gameobject
  3. align with view:将相机的位置变换到gameobject上,也即是GAME视角,

场景的对象的平移核导航操作可以利用类似的工具来完成:

  • 查看四周,按下鼠标右键可移动相机(此相机指的是我们看scene中的视图)。
  • 在使用相机的同时进行移动,按键ASDW
  • 按F键看缩放视角并聚焦与所选中的gameobject。

材料Materials

每个材料都有shader(着色器)这使得材质能够控制每个gameobject在场景的渲染的方式,每个shader负责将光照核纹理数据组合起来,进而让gameobject展现材质的样子。

transform类的变量和公共方法:

position:在世界空间坐标transform的位置。
localPosition:相对于父级的变换的位置。如果该变换没有父级,那么等同于Transform.position。
eulerAngles:世界坐标系中的旋转(欧拉角)。
localEulerAngles:相对于父级的变换旋转角度。
right:世界坐标系中的右方向。(世界空间坐标变换的红色轴。也就是x轴。)
up:世界坐标系中的上方向。(在世界空间坐标变换的绿色轴。也就是y轴。)
forward:世界坐标系中的前方向。(在世界空间坐标变换的蓝色轴。也就是z轴。)
rotation:世界坐标系中的旋转(四元数)。
localRotation:相对于父级的变换旋转角度。
localScale:相对于父级的缩放比例。
parent:父对象Transform组件。
worldToLocalMatrix:矩阵变换的点从世界坐标转为自身坐标(只读)。
localToWorldMatrix:矩阵变换的点从自身坐标转为世界坐标(只读)。
root:对象层级关系中的根对象的Transform组件。
childCount:子对象数量。
lossyScale:全局缩放比例(只读)。
1)Translate,用来移动物体的函数,非常常用的一个函数。
public void Translate (translation : Vector3, relativeTo : Space = Space.Self) : void
把物体向translation方向移动,距离为translation.magnitude。 relativeTo表示这个移动的参考坐标系。

public void Translate (x : float, y : float, z : float, relativeTo : Space = Space.Self) : void
同上

public void Translate (translation : Vector3, relativeTo : Transform) : void
如果relativeTo 不是null,则以目标物体relativeTo的自身轴向作为参考坐标系。

public void Translate (x : float, y : float, z : float, relativeTo : Transform) : void
同上

脚本:

var speed=30;

//将物体以30米每秒的速度向前移动。

trasform.Translate(Vector3.forward*speed*Time.deltaTime);
其中Time.dataTime指的是每一帧的间隔时间,这样做的好处是使得在任何机器上该游戏对象的每秒移动距离相同。

2)Rotate,用来旋转物体的函数,非常常用,在知道需要旋转的角度的情况下。如果要让物体旋转到指定位置,需要搭配Quaternion来使用。
public void Rotate (eulerAngles : Vector3, relativeTo : Space = Space.Self) : void
旋转eulerAngles度(3个轴向分别旋转),以relativeTo为参考坐标系

public void Rotate (xAngle : float, yAngle : float, zAngle : float, relativeTo : Space = Space.Self) : void
同上

public void Rotate (axis : Vector3, angle : float, relativeTo : Space = Space.Self) : void
以axis为轴旋转angle度,以relativeTo为参考坐标系

3)RotateAround 让物体以某一点为轴心成圆周运动。

public void RotateAround (point : Vector3, axis : Vector3, angle : float) : void

让物体以point为中心,绕axis为轴向旋转angle度。保持原来与point的距离。

让物体以point为中心,绕axis为轴向旋转angle度。保持原来与point的距离。

4)LookAt 让物体的z轴看向目标物体
public void LookAt (target : Transform, worldUp : Vector3 = Vector3.up) : void
让物体的z轴看向target的位置,并以worldUp为y轴指向方向。

public void LookAt (worldPosition : Vector3, worldUp : Vector3 = Vector3.up) : void
让物体看向worldPosition

5)TransformDirection
public Vector3 TransformDirection (direction : Vector3) : Vector3
返回以物体自身为坐标轴的向量direction在世界坐标中的朝向向量。

public Vector3 TransformDirection (x : float, y : float, z : float) : Vector3
同上

6)InverseTransformDirection
public Vector3 InverseTransformDirectionTransformDirection (direction : Vector3) : Vector3
public Vector3 InverseTransformDirectionTransformDirection (x : float, y : float, z : float) : Vector3
与TransformDirection相反,从世界坐标转换到自身相对坐标。

7)TransformPoint
public Vector3 TransformPoint (position : Vector3) : Vector3
public Vector3 TransformPoint (x : float, y : float, z : float) : Vector3
把一个点从自身相对坐标转换到世界坐标

8)InverseTransformPoint
public Vector3 InverseTransformPoint (position : Vector3) : Vector3
public Vector3 InverseTransformPoint (x : float, y : float, z : float) : Vector3
把一个点从时间坐标转换到自身坐标的位置。

9)DetachChildren
public void DetachChildren () : void
把自身所有的子物体的父物体都设成世界,也就是跟自己的所有子物体接触父子关系。

10)Find
public Transform Find (name : string) : Transform
找到一个名字是name的物体并返回

如果没有找到则返回null。如果字符串被/隔离,函数则会像文件路径一样逐级下查。

// The magical rotating finger
function Update() {
aFinger = transform.Find("LeftShoulder/Arm/Hand/Finger");
aFinger.Rotate(Time.deltaTime*20, 0, 0);
}

11)IsChildOf
public bool IsChildOf (parent : Transform) : bool
如果物体是parent的父子层级关系下的一员,返回true;

如何让变量在inspectors中可以调整

1)在类中设置变量为public
2)在变量前设置权限类型为[SerializeField],这杨字段var仍是private,但可以被inspector感知到。

[SerializeField] float var = 0.4f;

获取键盘输入值方法

Input.GetKey(KeyCode.键盘code)

刚体,碰撞检测

组件rigidbody

需要某个游戏对象能够走自由运动,则可以在游戏对象中添加组件rigidbody,这样游戏对象会有:质量,阻力,摩擦力,引力的影响。

image-20220316171823221
mass(质量)、linear drag(阻力)、angular drag(摩擦力)、gravity scale(引力)

组件collider

实现游戏对象的碰撞逻辑,可以根据游戏对象的形状,自动选择需要colider组件,例如:矩形对应Box Collider,边对应Edage collider等等。

通过程序逻辑实现碰撞事件响应

程序代码

void OnCollisionEnter2D(Collision2D other) {
        Debug.Log("撞到了!");
    }

需要检测刚体碰撞而又不想要游戏对象发生碰撞,也就是检测出两个游戏对象又发生碰撞但不会互相阻挡而是传过去。

1)在collisder组件里勾选 is trigger选项
2)在相应c#脚本内添加一个函数OntriggerEnter(),函数定义在类里面。

图片载入

将想要载入的图片直接拖入sprite render里的sprite

需要触发父gameobject内组件功能,使用transform.parent.GetComponent<>模板,需要什么组件则则就在<>内填写。

transform.parent.GetComponent<FloorManager>().CreateFloor();

Unity3D中的坐标系以及他们之间的相互转换

世界坐标

这个世界坐标unity中的全局坐标,每个Gameobject仅有一个全局坐标

屏幕坐标

屏幕坐标是以像素来定义的,它的范围是以左下角为(0,0),右上角为(Screen.width,Screen.height)定义的这样一个矩形。屏幕坐标是一个3D坐标,Z轴是以相机的世界单位来衡量的。屏幕坐标和相机之间满足:Screen.width=Camera.pixelWidth和Screen.height=Camera.pixelHeight这两个条件。例如我们将相机正对着场景中的<**在世界坐标中的原点**>原点(0,0,0),相机的Z轴分量为-10,按照屏幕坐标的定义,假设屏幕为800X640的大小,则此时原点转化为屏幕坐标后应该是(400,320,10)。在Unity3D中我们可以使用WorldToScreenPoint来将一个世界坐标转换为屏幕坐标。

视口坐标

视口坐标是标准化后的屏幕坐标。标准化的概念我们可以引申到向量的标准化中,比如一个向量(x,y)将过标准化后可以得到一个单位向量(x’,y’)。类似地,视口坐标是以0到1间的数字来表示的,它的范围是以左下角为(0,0),右上角为(1,1)定义的这样一个矩形。视口坐标是一个3D坐标,Z轴是以相机的世界单位来衡量的。通过对比可以发现视口坐标和屏幕坐标特别的相似,所以这里大家可以对比着来学习。同样以屏幕坐标中的例子来将这里的转换,例如我们将相机正对着场景中的原点(0,0,0),相机的Z轴分量为-10,按照屏幕坐标的定义,假设屏幕为800X640的大小,则此时原点转化为视口坐标后应该是(0.5,0.5,10)。在Unity3D中我们可以使用WorldToViewportPoint来将一个世界坐标转换为视口坐标。

GUI坐标

GUI坐标是指通过OnGUI方法绘制UI时使用的坐标。这个坐标系和屏幕坐标类似,它同样是以像素来定义的,它的范围是以左上角为(0,0),右下角为(Screen.width,Screen.height)定义的这样一个矩形,GUI坐标是一个2D坐标(绝对坐标)。

LocalPoaition和POSITION

localposition之的是本游戏对象相对于父对象的位置,以父对象的中心为原点,二position是全局坐标,当对象没有父母对象的时候,loaclposition与position相等。

二、给刚体施加力和加速度

2.1给刚体施加力

  1. 给刚体施加一个力以世界坐标为进行运动

    Rigidbody.AddForce(Vector3,ForceMode)

  2. 给刚体施加一个力以自身坐标进行运动

    Rigidbody.AddRelativeForce(Vector3,ForceMode

  3. 四种力的模式

    ForceMode.Force:给物体一个持续的力
    ForceMode.Acceleration:给物体一个持续的加速度,但是忽略其质量,质量被默认为1
    ForceMode.Impulse:给物体添加一个瞬间的力
    ForceMode.VelocityChange:给物体添加一个瞬间的加速度,忽略其质量

2.2获取刚体的速度

Rigibody r1,r2;
r1.velocity;

2.3Unity 控制物体旋转、朝向的一些方法

  1. transform. Lookat( )

    立即看向target的位置, 很生硬.
    transform.Lookat(target.position);
    
  2. 2,Quaternion.LookRotation( )

    transform.rotation = Quaternion.LookRotation(target.position - self.position);
    也是,立即看向target的位置。
    
  3. Quaternion.RotateTowards( )

    Quaternion q = Quaternion.LookRotation(target.position - self.position);
    Quaternion.RotateTowards(self.rotation, q, turnSpeed * Time.deltaTime);
    
    匀速转向target的位置。(匀速转过去, 虽然不那么生硬了, 但是还不够自然)
    
  4. Quaternion.Slerp( )

    Quaternion q = Quaternion.LookRotation(target.position - self.position);
    Quaternion.Slerp(self.rotation, q, turnSpeed * Time.deltaTime);
    非匀速转向target的位置。(人物转向看起来比较合理, 比较自然了)
    Lerp()方法是平分长度, Slerp()方法是平分弧度
    
  5. transform.Rotate ( )

    transform.rotate(Vector3.up, Space.Self);
    地球自转
    
  6. transform.RotateAround( )

    transform.rotateAround(sun.position, Vector3.up, turnSpeed * Time.deltaTime);
    绕太阳公转。
    
  7. 四元数*向量

    Vector3 dir = Quaternion.Euler(new Vector3(0, 0, angle)) * Vector3.right;
    将Vector3.right 饶Z轴 旋转angle度
    

    以下是DOTween的方法

  8. transform.DORotate(new Vector3(0, 60, 0), 0.3f);
    0.3秒转到(0, 60, 0); Rotation.DOTween的, 注意他的参数是个三元数, 要是想与另一个物体的朝向一致, 就:
    transform.DORotate(other.transform.eulerAngles, 0.3f);
    
  9. transform.DOLookAt()

transform.DOLookAt(other.transform, 0.3f)
还是DOTween的, 和transform.LookAt差不多, 设置个时间, 能达到lerp的效果, 还能在后面.SetEase(Ease.XXX);
加一些运动曲线

要知道正常游戏1帧=1次动画渲染,当你显卡不行,那么1秒可能只有20帧,如果追求极致,1秒可以144帧,也就是每帧不固定,这个时候就需要固定刷新时间/方法调用时间。特别是:在Update()方法中执行物理操作,会出现卡顿的情况

这样,所有和物理相关的操作,代码都要写在 FixedUpdate() 方法体内

FixedUpdate() 的固定更新的时间间隔是0.02秒,也就是1秒执行50次。

手动设置方法:Edit→Project Settings→Time面板,里面的Fixed Timestep参数即是时间间隔
img

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Text1: MonoBehaviour
{
    //因为Start()只会在开始游戏时被执行一次,所以一般都用来初始化
    private Transform myTransform;      //实例化Transform对象
    private Rigidbody myRigidbody;
    void Start()
    {
        Debug.Log("Start");     //输出调试
        myTransform = gameObject.GetComponent<Transform>();        //获取相应对象的引用
        myRigidbody = gameObject.GetComponent<Rigidbody>();
    }
    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.W))
        {
            Debug.Log("刚体向前移动");
            myRigidbody.MovePosition(myTransform.position + (new Vector3(0, 0, 1)));
        }
        if (Input.GetKeyDown(KeyCode.A))
        {
            Debug.Log("刚体向左移动");
            myRigidbody.MovePosition(myTransform.position + (new Vector3(-1, 0, 0)));
        }
        if (Input.GetKeyDown(KeyCode.S))
        {
            Debug.Log("刚体向后移动");
            myRigidbody.MovePosition(myTransform.position + (new Vector3(0, 0, -1)));
        }
        if (Input.GetKeyDown(KeyCode.D))
        {
            Debug.Log("刚体向右移动");
            myRigidbody.MovePosition(myTransform.position + (new Vector3(1, 0, 0)));
        }
    }
    void FixedUpdate()
    {
        if (Input.GetMouseButtonDown(1))            //按下鼠标右键
            myRigidbody.AddForce(new Vector3(0, 0, -3), ForceMode.Impulse);
        if (Input.GetMouseButton(0))                //压住鼠标左键
            myRigidbody.AddForce(new Vector3(0, 0, -10), ForceMode.Force);
    }
}

相机移动跟随

public class CameraBehavior:MonoBehaviour
{
    public Vector3 canOffset = new Vector3(0,1.2,--2.6);
    private Transform target;
    void Start)(){
        target - GameObject.Find("player").transform;
    }
    void lateUpdate()//在update方法之后执行,因为update方法会改变target的位置,所以在update方法后执行能够确保相机的在target最新位置相对位置。
    {
        this.transform.position = target.TransformPoint(camOffet);
        //TransFORMpOINt方法适用于计算并返回世界空间的相对位置。
        this.tranform.LookAt(target):
        //确保相机跟谁目标一起旋转
    }
}

awake函数

用于初始化变量和游戏状态。

使用

当一个脚本实例被载入时awake被调用,所有awake函数在每个场景加载完后就依次被调度执行,在start函数之前执行,一般尽在runtime模式执行,除非在在每个类前面假说属性attribute[[ExecuteInEditMode]],才会在在编辑模式执行,

  • 用法一:可以在awake里面设置enable值(默认为true),使得该脚本的start函数和update函数无法被调用。

    
    public class Test : MonoBehaviour {
        void Awake () {
            Debug.Log("Awake");
            enabled = false;
        }
     
        void Start () {
            Debug.Log("Start");
        }
    
    

    而在游戏过程中会有另一段代码被执行

    Test test = go.GetComponent<Test>();
    test.enabled = true;
    

    这段代码被执行之后,start方法才能被调用

  • 设置被引用的object(reference)

    //player.cs
    private Transform handAnchor = null;
    void Awake () { handAnchor = transform.Find("hand_anchor"); }
    // void Start () { handAnchor = transform.Find("hand_anchor"); }
    void GetWeapon ( GameObject go ) {
        if ( handAnchor == null ) {
            Debug.LogError("handAnchor is null");
            return;
        }
        go.transform.parent = handAnchor;
    }
    //othrer.cs
    ...
    GameObject go = new GameObject("player");
    player pl = go.AddComponent<player>(); // Awake invoke right after this!
    pl.GetWeapon(weaponGO);
    ...
    

    以上代码中,我们在player Awake的时候去为handAnchor赋值。如果我们将这步操作放在Start里,那么在other.cs中,当执行GetWeapon的时候就会出现handAnchor是null reference.

setactive函数

控制整个gameobject的激活状态,当处于未激活状态时候,此gameobject将停用所有附加在其上面的组件功能,也就是对所有组件调用Onenable函数

标签:float,C#,void,Vector3,transform,学习,unity,坐标,public
From: https://www.cnblogs.com/NCU-zjf/p/16804598.html

相关文章

  • maven的<scope>
    放到dependencyManagement之后子项目必须显示的声明,而其他会直接继承......
  • 2022下半年 Acwing 第二篇:归并模板
    归并其实和快排比较类似,所以模板的记忆也大差不差。不能省懒!voidmerge_sort(intq[],intl,intr){if(l>=r)return;intmid=l+r>>1;merge_s......
  • 工作笔记之 SELECT 语句在 SAP ABAP 中的用法总结(上)
    日常开发过程中,最常用的语句可能就是查询语句了。那么如果从数据库表中查询数据呢?答:​​selectfrom​​语句。SELECT的三个部分在OPENSQL中,​​SELECT​​语句可以查......
  • leetcode 380. Insert Delete GetRandom O(1) O(1) 时间插入、删除和获取随机元素 (
    一、题目大意实现RandomizedSet类:RandomizedSet()初始化RandomizedSet对象boolinsert(intval)当元素val不存在时,向集合中插入该项,并返回true;否则,返回false......
  • Canal
    CanalCanal介绍    功能:通过读取Mysql的Binlog,实时采集数据库数据的变化写到消息队列。    原理:将自己伪装成Slave,假装从Master复制数据    使用场景:1.异地......
  • 群晖后台安装 ipkg 包管理 和 screen
    wgethttp://ipkg.nslu2-linux.org/feeds/optware/syno-i686/cross/unstable/syno-i686-bootstrap_1.2-7_i686.xshchmod+xsyno-i686-bootstrap_1.2-7_i686.xshshsyno......
  • Accurate Decentralized Application Identification via Encrypted Traffic Analysis
    AccurateDecentralizedApplicationIdentificationviaEncryptedTrafficAnalysisUsingGraphNeuralNetworks--论文解读利用图神经生成去中心化软件的指纹----一......
  • 登录(cookie,session)
    cookie和登录校验cookie:存储在浏览器的一段字符串,最大5kb,每个域都有一个cookie,跨域不共享,格式如k1=v1;k2=v2(可结构化)cookie会随http请求传递给服务端每次http请求,coo......
  • C源代码程序如何转换为可执行文件
    #gcc生成intel风格的汇编gcc-S-masm=intelsample.c-osample.s一、C源代码文件如何成为可执行文件以helloworld.c为例,说明C语言源代码文件如何变成可执行文件的,经......
  • C语言实例3
    题目:在100内,一个整数,它加上100后是一个完全平方数,再加上168又是一个完全平方数,请问该数是多少?程序分析:在100以内判断,先将该数加上100后再开方,再将该数加上268后再开方,如......