Unity、C#、Lua面试题整理(持续更新)

一:什么是协同程序?

 答:在主线程运行时同时开启另一段逻辑处理,来协助当前程序的执行。换句 话说,开启协程就是开启一个可以与程序并行的逻辑。可以用来控制运动、序列以及对象的行为。

二:Unity3d中的碰撞器和触发器的区别?

 答:碰撞器是触发器的载体,而触发器只是碰撞器身上的一个属性。 当Is Trigger=false时,碰撞器根据物理引擎引发碰撞,产生碰撞的效果,可以 调用OnCollisionEnter/Stay/Exit函数; 当Is Trigger=true时,碰撞器被物理引擎所忽略,没有碰撞效果,可以调用 OnTriggerEnter/Stay/Exit函数。 如果既要检测到物体的接触又不想让碰撞检测影响物体移动或要检测一个物件 是否经过空间中的某个区域这时就可以用到触发器

三:物体发生碰撞的必要条件

 答:两个物体都必须带有碰撞器Collider,其中一个物体还必须带有Rigidbody 刚体。

四:请简述ArrayList和List<Int>的主要区别

      答: ArrayList存在不安全类型

             • ArrayList会把所有插入其中的数据都当做Object来处理  

             • 装箱拆箱的操作

              List是接口,ArrayList是一个实现了该接口的类,可以被实例化

 

五:装箱操作和拆箱分为那几个步骤:

(1)内存分配:在托管堆中分配内存空间用来存放复制的实际数据

(2)完成实际数据的复制:将值类型实例的实际数据复制到新分配的内存中

(3)地址返回:将托管堆中的对象地址返回给引用类型变量

拆箱分为以下三个步骤:

(1)检查实例:首先检查进行拆箱操作的引用类型是否为null,如果为null则抛出异常,如果不为null则继续检查变量是否和拆箱后的类型是同一类型。

(2)地址返回:返回已装箱变量的实际数据部分的地址

(3)数据复制:将托管堆中的实际数据复制到栈中

 

六:简述GC产生的原因,并描述如何避免

      答:GC回收堆上的内存

      避免:1.减少new产生对象的次数;2.使用公共对象成员(静态变量);3.将string类型换位stringBuilder

七:反射的实现原理

     答:审查元数据并收集关于它类型信息的能力,实现步骤:

      • 导入using System.Reflection;

      • Assembly.Load("程序集");//加载程序集,返回类型是一个Assembly

      • 得到程序集中所有类的名称 foreach (Type type in assembly.GetTypes())

      • {  •   string t = type.Name;  • }

      • Type type = assembly.GetType("程序集.类名");//获取当前类的类型  

      • Activator.CreateInstance(type); //创建此类型实例  

      • MethodInfo mInfo = type.GetMethod("方法名");//获取当前方法  

      • mInfo.Invoke(null,方法参数);

 

八:简述四元数Quaternion的作用,四元数对欧拉角的优点。常见的四元数函数有哪些,有什么作用:

       答:四元数表示旋转

       相对于欧拉角的优点:

       1.可以进行增量旋转;2.避免万向锁;3.给定方位的表达式互为负(欧拉角有无数种表达方式)

  一、Quaternion.LookRotation

    声明形式:public static Quaternion LookRotation ( Vector3 forward, Vector3 upwards=Vector3.up )

    这个功能很实用,传入的两个参数分别代表前方盯着的方向以及自己的上方向。它可以让一个GameObject转动脑袋盯着另一个物体。如:

    public Transform target;
    void Update() {
        Vector3 relativePos = target.position - transform.position;
        Quaternion rotation = Quaternion.LookRotation(relativePos);
        transform.rotation = rotation;
    }
    这段代码就可以让当前的object时时盯着target不放,当然,你也可以自定义up朝向,这里默认是Vector3.up。

 

    二、Quaternion.Angle

    声明形式:public static float Angle ( Quaternion a, Quaternion b )

    这个就比较简单了,它可以计算两个旋转之间的夹角。与Vector3.Angle()作用是一样的。

 

    三、Quaternion.Euler

    声明形式:public static Quaternion Euler ( float x, float y, float z ),或者:    public static Quaternion Euler ( Vector3 euler )

    这个函数可以将一个欧拉形式的旋转转换成四元数形式的旋转。传入的参数分别是欧拉轴上的转动角度。

 

    四、Quaternion.Lerp 和 Quaternion.Slerp

    声明形式:public static Quaternion Slerp ( Quaternion from, Quaternion to, float t )

    基本意思就是线性地从一个角度旋转到另一个角度,其中,旋转匀速增加t。

  附加内容:很多时候from 和to都不是固定的,而且上一个脚本也不能保证所有角度下的旋转速度一致。所以我写了这个脚本来保证可以应付大多数情况。

        Transform target;
        float rotateSpeed = 30.0f;

        Quaternion wantedRotation = Quaternion.FromToRotation(transform.position, target.position);
        float t = rotateSpeed/Quaternion.Angle(transform.rotation, wantedRotation)*Time.deltaTime;
        transform.rotation = Quaternion.Slerp(transform.rotation, target.rotation, t);

    这个脚本可以保证物体的旋转速度永远是rotateSpeed。如果自身坐标和目标之间的夹角是X度,我们想以s=30度每秒的速度旋转到目标的方向,则每秒旋转的角度的比例为s/X。 再乘以每次旋转的时间Time.deltaTime我们就得到了用来匀速旋转的t。

 

    五、FromToRotation

    声明形式:public static Quaternion FromToRotation ( Vector3 from, Vector3 to )

    它是得到从一个方向到另一个方向的旋转。就是转一个方向,就这么简单。

九:如何安全的在不同工程间安全的迁移asset数据:

答:1.将Asset和Library一起迁移

       2.导出包package

       3. 用unity自带的assets Server功能

 

 

十:Unity程序在运行时的生命周期的执行顺序?哪些可能在同一个对象周 期中反复的发生?

 答:Awake–>OnEnable->Start ->Update->FixedUpdate->LateUpdate->OnDisable->OnDestroy

OnEnable在同一周期中可以反复地发生!

十一:MeshRender中material和sharedmaterial的区别?

 答: 修改sharedMaterial将改变所有物体使用这个材质的外观,并且也改变储存在工程里的材质设置。 不推荐修改由sharedMaterial返回的材质。如果你想修改渲染器的材质,使用 material替代

十二:TCP/IP协议栈各个层次即分别的功能:

答:网络接口层:这是协议栈的最底层,对应OSI(开放式系统互联通信参考模型)的物理层和数据链路层,主要完成数据帧的实际发送和接受

网络层:处理分组在网络中的活动,例如路由器的选择和转发等,这一层主要包括IP协议、ARP、ICMP协议

传输层:主要功能是提供应用程序之间的通信,这一层是TCP/UDP协议

应用层:用来处理特定的应用,针对不同的应用提供了不同的协议,例如进行文件传输时用到的FTP协议,发送email用到SMTP协议

十三:Uinity提供了几种光源,分别是什么:

答:平行光:Directional Light、点光源:Point Light、聚光灯:Spot Light、区域光源:Area Light

十四:简述一下对象池,你觉得在FPS里哪些东西适合使用对象池?

答: 对象池就存放需要被反复调用资源的一个空间,比如游戏中要常被大量复制的 对象,子弹,敌人,以及任何重复出现的对象。

十五:CharacterController和Rigidbody的区别?

答: Rigidbody具有完全真实物理的特性,而CharacterController可以说是受限的 的Rigidbody,具有一定的物理效果但不是完全真实的。

十六:Lua迭代器的实现:

function deiDaiQi(t)
local i=0
return function() //闭合函数
i=i+1
return t[i] 
end
end

--调用:
local iter=deiDaiQi(t)
while(true) do
local value=lter()
if value==nil then
break;
end
else
print(value)

十七:Lua继承实现

--面向对象简易版
Hero={attack=10}
function Hero:new(o)
    o=o or {}
    Setmetatable(o,self)
    self.__index=self
    return o
end

function Hero:Skill(attackNumber)
    print(self.attack+attackNnumber)
end

--调用
Loacl child=Hero:new()

--面向对象Class类

function class(classname, super) 
 local superType = type(super) 
 local cls 
 -- inherited from Lua Object 
 if super then 
     cls = {} 
     setmetatable(cls, {__index = super}) 
     cls.super = super 
 else 
     cls = {ctor = function() end} 
 end 
 
 cls.__index = cls 
 function cls.new(...) 
     local instance ={}
     Setmetatable({}, cls)  
     instance:ctor(...) 
     return instance 
 end 
 return cls 
end


-- 调用
-- 定义名为Sharp的基础类
local Shape =class("Shape")

-- ctor() 是类的构造函数,在调用Shape.new()创建Shape对象的时候会自动调用
function Shape:ctor(shapeName)
    self.shapeName=shapeName
    print("Shape:ctor",self.shapeName)
end

-- 为Shape定义名为draw()方法
function Shape:draw()
    print("draw",self.shapeName)
end

-- Circles 是 Shape的继承类
local Circles=class("Circles",Shape)
function Circles:ctor()

    --如果继承类覆盖了 ctor()构造函数,那么必须手动调用父类的构造函数
    --类型.super可以访问指定类的父类
    --self=Clireles,显式传递self给父类,父类会调用当前传递的self
    Clircles.super.ctor(self,"circles")   
    self.redius=100
end

function Circles:setRaduis(radius)
    self.redius=radius
end

-- 覆盖父类的同名方法
function Circles:draw()
    print(self.shapName,self.radius)
end

local circle=Clrcles:new()
circle:setRadius(200)
circle:draw()              -- 输出 circles,200

十八:请描述C#的值类型和引用类型的区别

答:值类型被分配在线程栈中,变量保存的就是数据本身

引用类型被分配在托管堆中,变量保存的是实例数据的内存地址

值类型默认值是0,引用类型默认值是null

值类型继承自System.ValueType,引用类型继承自System.Object

十九:递归实现斐波拉契数列

public int Fb(int n)
{
    if(n==1 || n==2)
    {
        return 1;
    }
    else
        return Fb(n-1)+Fb(n-2);
}

二十:请分别使用委托、匿名函数、以及Lambada来实现两个数求和,已知委托如下 delegate int Add(int a,int b)

public delegate int Add(int a, int b);


 Add add = delegate (int a, int b) { return a + b; };
 Add add1 = (int a, int b) => { return a + b; };
 Add add2 = Ad;
 Func<int, int, int> func = (a, b) => { return a + b; };



public int Ad(int a, int b)
 {
    return a + b;
 }

二十一:向量的点乘、叉乘、和归一化的意义

答:向量归一化就是向量的单位向量 可以结合向量的点乘判断 向量之间的夹角 是否垂直或者大于九十度小于九十度

向量的叉乘得到两向量所在平面的法向量,可以用于物体旋转

二十二:代码实现单例模式

public class Manager
{
    private Manager instance;
    public Manager Instance
    {
        get
        {
            if (instance == null)
            {
                instance = new Manager();
            }
            return instance;
        }
    }
}

二十三:内存优化

https://blog.csdn.net/liu943367080/article/details/93773336

 

 

 

 

 

 

  • 3
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值