Unity2019 C# 使用指针unsafe记录 and 替代方法

3 篇文章 0 订阅

参考:https://blog.csdn.net/weixin_34071713/article/details/91505798(网上所有Unity指针说明都一样,大多数都一字不差,可能是同一个博主吧).

根据我成功的经验总结一下,想要在Unity中使用指针大概分为以下几个步骤(相对参考的文章有些地方有更新):

1.第一步:

Edit-ProjectSetting-Player-OtherSetting-Configuration-Allow 'unsafe' Code勾选上.(可能使因为版本更新,网上的步骤提示的路径根本找不到Allow 'unsafe' Code,我使根据Unity报错找到的,报错显示其在"Playerstting中").

2.第二步:

打开记事本->记录一句'-unsafe'(不带单引号哦,就是-unsafe)->保存->命名为us.rsp->把该文件放在项目文件Asset文件中.

(参考文章中,不同的语言要起不同的文件名,具体看下面表格,我用的Unity,所以就用了us.rsp,编辑器模式下反正是成功了.顺便一提,我参考的文章中是用的smcs.rsp,并且提示"说需要重启Unity,且工程文件名不能有中文,该文件的原理是编辑器中的smcs.exe 添加编译命令,也可以在CMD下运行编辑器目录下的smcs.exe  逐个添加,就是比较麻烦".)

C#<Project Path>/Assets/smcs.rsp
C# - Editor Scripts<Project Path>/Assets/gmcs.rsp
UnityScript<Project Path>/Assets/us.rsp
Boo<Project Path>/Assets/boo.rsp

3第三步:

用代码测试:

->复制下面的网上测试用的代码到你们的代码中

unsafe void test () 
{
    int i=10;
    int k;
    int *j=&i;      
    k=*j+1;
    print("unsafe test " + k.ToString());
}

->注意:在引用的的函数前面加上unsafe,若多层引用则每层函数前面都要加上unsafe.同理,在Update或FixedUpdate或Awake或Start等等系统函数里引用,他们前面也要加上unsafe.

(不加unsafe的话,编辑器会报错说unsafe只能用在unsafe的上下文中,因为这个问题我纠结了挺久,导致后来没用指针,而是用了数组,因为数组名也是指针类型,结果后来一想可能需要都加unsafe,结果一试真的成功了).

->如果Unity运行后,Console窗口打印"11",就是成功了.

 

最近发现的其他代替方法:

1.ref引用参数:

C#的两种类型包括"值类型"和"引用类型"两种,引用变量和数组名比较像,比如在函数的形参为引用类型的变量,会改变传入的实参的值,类似于指针的地址传递;而值变量若作为函数的参数传递时,是值传递,不会改变实参的值.

C#语言中有一种参数叫"引用参数(用ref修饰的参数)",这是可以取代指针的一个办法:

形式参数的声明格式:(ref 参数类型 参数名)

2.out输出参数:

与ref作用相似,但是ref修饰的参数,实参把地址传给形参,此时他们代表的是同一个内容(同一段物理地址的内容),形参改变,实参也改变;而out修饰的参数,填入的实参只是把地址给形参,但内容不会传给形参,就是说在函数中不能引用值(内容里的值),只能并且必须在函数中给它赋值.

有位大神总结一句话就是:ref有进有出,out只出不进(所以ref需要有初始值传入,而out不需要初始值).

形式参数的声明格式:(out 参数类型 参数名)

3.params动态数组参数:

若用params修饰数组型的参数,则填入实参的方法可以容许更多种.

比如形参为int型数组,填入实参时除了可以是数组,还可以是"fuction(1,1,1,1)多个int型常量".

若是形参为Object类型数组,则填入实参时,若是填入一个Object型数组,怎会把该数组中每一个元素都当作是一个元素传给形参;若是"fuction(Object[ ] Objs,1,1,1)",则会把Objs当作一个元素传给形参.

4.委托类:

原理就是委托类型的名(其实是个类).

1) 委托类可以作为其他函数的参数类型,因此可以用一行取代一次判断,从而减少If..else或者Switch case等大量占篇幅.

private delegate void function1(int n);    //声明要作为函数参数的function1类为委托类型
private void function2(int n,function1 function1_1)  //用委托类型的函数做参数,实参可以传入与function1同样的void类型的函数名
void
{
    function1_1(n);
}

2) 委托类可以使用"+="把其他类中的函数添加到委托类中(订阅),或者从委托类中删除(取消订阅),(记得声明/定义/新建类),然后调用委托类从而调用(触发)其中添加的函数.

//委托
using System;
using System.Collections.Generic;
using UnityEngine;

public class CLASS1()                   //被使用函数
{
    public void fuction1()
    {
        print("CLASS1.fuction1");
    }
}

public class CLASS2()                   //被使用函数
{
    public void fuction2()
    {
        print("CLASS2.fuction2");
    }
}

public detegate void DetegateClass();   //声明委托类
public class CLASS3()
{
    public DetegateClass detegate;      //定义委托类
}

public class CLASS4()
{
   private Start()
    {
        CLASS1 c1=new CLASS1();
        CLASS2 c2=new CLASS2();
        CLASS2 c3=new CLASS3();
        c3.detegate+=c1.fuction1;       //把其他类的函数添加到委托类里(可以加入多个)
        c3.detegate+=c2.fuction2;       
        c3.detegate();                  //调用委托类里增加的函数
    }
}

5.事件:

事件是委托的封装,更安全,可以添加调用条件.

事件类可以把其他类中的方法函数添加到事件中,但是不能直接像"委托"一样直接调用已添加的函数,必须在定义委托类的类中,再定义一个调用该事件的公共方法函数供外部调用.

//事件
using System;
using System.Collections.Generic;
using UnityEngine;

public class CLASS1()                     //被使用函数
{
    public void fuction1()
    {
        print("CLASS1.fuction1");
    }
}

public class CLASS2()                     //被使用函数
{
    public void fuction2()
    {
        print("CLASS2.fuction2");
    }
}

public detegate void DetegateClass();     //声明委托类
public class CLASS3()
{
    /*public DetegateClass detegate;      //定义委托类*/
    public event DetegateClass detegate;  //定义事件类
    public void eventCall()
    {
        detegate();
    }
}

public class CLASS4()
{
   private Start()
    {
        CLASS1 c1=new CLASS1();
        CLASS2 c2=new CLASS2();
        CLASS2 c3=new CLASS3();
        c3.detegate+=c1.fuction1;       //把其他类的函数添加到事件类里(可以加入多个)
        c3.detegate+=c2.fuction2;       
        /*c3.detegate();                //调用委托类里增加的函数*/
        c3.eventCall();                 //调用时间类里增加的函数
    }
}

关于"委托"和"事件"参考文章:https://blog.csdn.net/q493201681/article/details/82352616

 

 

 

 

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值