Unity3D 实用技巧 - 基础知识大全集(二)

实现炫酷可视化大屏,three.js 与 Unity3D技术对比 实现炫酷可视化大屏,选择three还是u3d? 阅读详情

高阶内容

Part1:C#代码类
1、 C#和C++的区别?
简单的说:C# 与C++ 比较的话,最重要的特性就是C# 是一种完全面向对象的语言,而C++ 不是,另外C# 是基于IL 中间语言和.NET Framework CLR 的,在可移植性,可维护性和强壮性都比C++ 有很大的改进。C# 的设计目标是用来开发快速稳定可扩展的应用程序,当然也可以通过Interop和Pinvoke 完成一些底层操作。
2、 请简述sealed关键字用在类声明时与函数声明时的作用。
类声明时可防止其他类继承此类,在方法中声明则可防止派生类重写此方法。
3、 简述一下对象池,你觉得在FPS里哪些东西适合使用对象池?
对象池就存放需要被反复调用资源的一个空间,比如游戏中要常被大量复制的对象,子弹,敌人,以及任何重复出现的对象。
4、 C#中四种访问修饰符是哪些?各有什么区别?
四种访问修饰符是:属性修饰符、存取修饰符、类修饰符、成员修饰符
a. 属性修饰符:
Serializable:按值将对象封送到远程服务器。
STATread:是单线程套间的意思,是一种线程模型。
MATAThread:是多线程套间的意思,也是一种线程模型。
b. 存取修饰符:
public:存取不受限制。
private:只有包含该成员的类可以存取。
internal:只有当前命名空间可以存取。只能在包含该类的程序集中访问该类。
protected:只有包含该成员的类以及派生类可以存取。
protected internal:protected + internal
c. 类修饰符:
abstract:抽象类。指示一个类只能作为其它类的基类。
sealed:密封类。指示一个类不能被继承。理所当然,密封类不能同时又是抽象类,因为抽象总是希望被继承的。
d. 成员修饰符:
abstract:指示该方法或属性没有实现。
sealed:密封方法。可以防止在派生类中对该方法的override(重载)。不是类的每个成员方法都可以作为密封方法密封方法,必须对基类的虚方法进行重载,提供具体的实现方法。所以,在方法的声明中,sealed修饰符总是和override修饰符同时使用。
delegate:委托。用来定义一个函数指针。C#中的事件驱动是基于delegate + event的。
const:指定该成员的值只读不允许修改。
event:声明一个事件。
extern:指示方法在外部实现。
override:重写。对由基类继承成员的新实现。
readonly:指示一个域只能在声明时以及相同类的内部被赋值。
static:指示一个成员属于类型本身,而不是属于特定的对象。即在定义后可不经实例化,就可使用。
virtual:指示一个方法或存取器的实现可以在继承类中被覆盖。
new:在派生类中隐藏指定的基类成员,从而实现重写的功能。 若要隐藏继承类的成员,请使用相同名称在派生类中声明该成员,并用 new 修饰符修饰它。
5、 请简述ArrayList和List<Int>的主要区别?
a. ArrayList存在不安全类型,ArrayList会把所有插入其中的数据都当做Object来处理、装箱拆箱的操作;
b. List是接口,ArrayList是一个实现了该接口的类,可以被实例化。
6、 请简述GC(垃圾回收)产生的原因,并描述如何避免?
GC产生的原因:回收堆上的内存
避免:
a. 减少new产生对象的次数
b. 使用公用的对象(静态成员)
c. 将String换为StringBuilder
7、 反射的实现原理?
原理:审查元数据并收集关于它的类型信息的能力。
实现步骤:
a. 导入using System.Reflection;
b. Assembly.Load("程序集");//加载程序集,返回类型是一个Assembly;
c. 得到程序集中所有类的名称。
    
foreach ( Type type in assembly . GetTypes ( ) ) { string t = type . Name ; } Type type = assembly . GetType ( "程序集.类名" ) ; //获取当前类的类型 Activator . CreateInstance ( type ) ; //创建此类型实例 MethodInfo mInfo = type . GetMethod ( "方法名" ) ; //获取当前方法 mInfo . Invoke ( null , 方法参数 ) ;
8、 请描述Interface与抽象类之间的不同。
抽象类表示该类中可能已经有一些方法的具体定义,但接口就是公公只能定义各个方法的界面 ,不能具体的实现代码在成员方法中。类是子类用来继承的,当父类已经有实际功能的方法时该方法在子类中可以不必实现,直接引用父类的方法,子类也可以重写该父类的方法。实现接口的时候必须要实现接口中所有的方法,不能遗漏任何一个。
9、 .Net与Mono的关系?
Mono是.Net的一个开源跨平台工具,就类似Java虚拟机,Java本身不是跨平台语言,但运行在虚拟机上就能够实现了跨平台。.Net只能在Windows下运行,Mono可以实现跨平台编译运行,可以运行于Linux,Unix,Mac OS等。
10、 简述Unity3D支持的作为脚本的语言的名称。
Unity的脚本语言基于Mono的.Net平台上运行,可以使用.NET库,这也为XML、数据库、正则表达式等问题提供了很好的解决方案。Unity里的脚本都会经过编译,他们的运行速度也很快。这三种语言实际上的功能和运行速度是一样的,区别主要体现在语言特性上。主要使用语言:JavaScript、 C#、Boo。
11、 Heap与Stack有何区别?
a. Heap是堆,Stack是栈。
b.Stack的空间由操作系统自动分配和释放,Heap的空间是手动申请和释放的,Heap常用New关键字来分配。
c.Stack空间有限,Heap的空间是很大的自由区。
12、 值类型和引用类型有何区别?
a. 值类型的数据存储在内存的栈中;引用类型的数据存储在内存的堆中,而内存单元中只存放堆中对象的地址。
b. 值类型存取速度快,引用类型存取速度慢。
c. 值类型表示实际数据,引用类型表示指向存储在内存堆中的数据的指针或引用。
e. 值类型继承自System.ValueType,引用类型继承自System.Object。
f. 栈的内存分配是自动释放;而堆在.NET中会有GC来释放。
g. 值类型的变量直接存放实际的数据,而引用类型的变量存放的则是数据的地址,即对象的引用。
h. 值类型变量直接把变量的值保存在堆栈中,引用类型的变量把实际数据的地址保存在堆栈中。
13、 结构体和类有何区别?
结构体是一种值类型,而类是引用类型。(值类型、引用类型是根据数据存储的角度来分的)。就是值类型用于存储数据的值,引用类型用于存储对实际数据的引用。那么结构体就是当成值来使用的,类则通过引用来对实际数据操作。
14、 请写出求斐波那契数列任意一位的值得算法
    
static int Fn ( int n ) { if ( n <= 0 ) { throw new ArgumentOutOfRangeException ( ) ; } if ( n == 1 || n == 2 ) { return 1 ; } return checked ( Fn ( n - 1 ) + Fn ( n - 2 ) ) ; // when n>46 memory will overflow }
15、 ref参数和out参数是什么?有什么区别?
ref和out参数的效果一样,都是通过关键字找到定义在主函数里面的变量的内存地址,并通过方法体内的语法改变它的大小。
区别:
a. 就是输出参数必须对参数进行初始化。
b. ref参数是引用,out参数为输出参数。
16、 C#的委托是什么?有何用处?
C#的委托类似于一种安全的指针引用,在使用它时是当做类来看待而不是一个方法,相当于对一组方法的列表的引用。
用处:使用委托使程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码,而不必在编译时知道将调用哪个方法。与C或C++中的函数指针不同,委托是面向对象,而且是类型安全的。
17、 什么是里氏代换元则?
里氏替换原则(Liskov Substitution Principle LSP)面向对象设计的基本原则之一。 里氏替换原则中说,任何基类可以出现的地方,子类一定可以出现,作用方便扩展功能。
18、 Mock和Stub有何区别?
Mock与Stub的区别:Mock:关注行为验证。细粒度的测试,即代码的逻辑,多数情况下用于单元测试。Stub:关注状态验证。粗粒度的测试,在某个依赖系统不存在或者还没实现或者难以测试的情况下使用,例如访问文件系统,数据库连接,远程协议等。
19、 概述序列化:
序列化简单理解成把对象转换为容易传输的格式的过程。比如,可以序列化一个对象,然后使用HTTP通过Internet在客户端和服务器端之间传输该对象。
20、 堆和栈的区别?
a. 栈由系统自动分配,而堆是人为申请开辟;
b. 栈获得的空间较小,而堆获得的空间较大;
c. 栈由系统自动分配,速度较快,而堆一般速度比较慢;
d. 栈是连续的空间,而堆是不连续的空间;
e. 堆像是一个仓库,储存着我们使用的各种对象等信息,跟栈不同的是他们被调用完毕不会立即被清理掉。
21、 概述c#中代理和事件?
代理就是用来定义指向方法的引用,C#事件本质就是对消息的封装,用作对象之间的通信;发送方叫事件发送器,接收方叫事件接收器。
22、 C#中的排序方式有哪些?
排序方式:选择排序,冒泡排序,快速排序,插入排序,希尔排序,归并排序
23、 客户端与服务器交互方式有几种?
Socket通常也称作"套接字",实现服务器和客户端之间的物理连接,并进行数据传输,主要有UDP和TCP两个协议。Socket处于网络协议的传输层。
Http协议传输的主要有Http协议 和基于Http协议的Soap协议(Web Service),常见的方式是 Http 的Post 和Get 请求,Web 服务。
24、 能用foreach遍历访问的对象需要实现 接口或声明 方法的类型?
IEnumerable接口、GetEnumerator方法
25、 重载和重写的区别?
a. 封装、继承、多态所处位置不同,重载在同类中,重写在父子类中。
b. 定义方式不同,重载方法名相同参数列表不同,重写方法名和参数列表都相同。
c. 调用方式不同,重载使用相同对象以不同参数调用,重写用不同对象以相同参数调用。
d. 多态时机不同,重载时编译时多态,重写是运行时多态。
26、 面向对象的三大特点
a. 继承: 提高代码重用度,增强软件可维护性的重要手段,符合开闭原则。继承最主要的作用就是把子类的公共属性集合起来,便与共同管理,使用起来也更加方便。你既然使用了继承,那代表着你认同子类都有一些共同的特性,所以你把这些共同的特性提取出来设置为父类。继承的传递性:传递机制 a->b; b->c; c具有a的特性 。继承的单根性:在C#中一个类只能继承一个类,不能有多个父类。
b.封装: 封装是将数据和行为相结合,通过行为约束代码修改数据的程度,增强数据的安全性,属性是C#封装实现的最好体现。就是将一些复杂的逻辑经过包装之后给别人使用就很方便,别人不需要了解里面是如何实现的,只要传入所需要的参数就可以得到想要的结果。封装的意义在于保护或者防止代码(数据)被我们无意中破坏。
c.多态性: 多态性是指同名的方法在不同环境下,自适应的反应出不同得表现,是方法动态展示的重要手段。多态就是一个对象多种状态,子类对象可以赋值给父类型的变量。
27、 反射的实现原理?
可以在加载程序运行时,动态获取和加载程序集,并且可以获取到程序集的信息反射即在运行期动态获取类、对象、方法、对象数据等的一种重要手段。
主要使用的类库:System.Reflection
核心类:
a. Assembly描述了程序集
b. Type描述了类这种类型
c. ConstructorInfo描述了构造函数
d. MethodInfo描述了所有的方法
e. FieldInfo描述了类的字段
f. PropertyInfo描述类的属性
通过以上核心类可在运行时动态获取程序集中的类,并执行类构造产生类对象,动态获取对象的字段或属性值,更可以动态执行类方法和实例方法等。
28、 在类的构造函数前加上Static会报什么错?为什么?
构造函数格式为Public+类名如果加上 Static 会报错(静态构造函数不能有访问、型的对象,静态构造函数只执行一次;运行库创建类实例或者首次访问静态成员之前,运行库调用静态构造函数;静态构造函数执行先于任何实例级别的构造函数;显然也就无法使用this和 base 来调用构造函数。
29、 C# String类型比 StringBuilder 类型的优势是什么?
a. 如果是处理字符串的话,用String中的方法每次都需要创建一个新的字符串对象并且分配新的内存地址,而 StringBuilder 是在原来的内存里对字符串进行修改,所以在字符串处理方面还是建议用stringBuilder这样比较节约内存。但是 string 类的方法和功能仍然还是比 stringBuilder 类要强。
b. String类由于具有不可变性(即对一个 string 对象进行任何更改时,其实都是创建另外一个 string 类的对象),所以当需要频繁的对一个 string 类对象进行更改的时候,建议使用StringBuilder 类,StringBuilder 类的原理是首先在内存中开辟一定大小的内存空间,当对此 StringBuilder 类对象进行更改时, 如果内存空间大小不够, 会对此内存空间进行扩充,而不是重新创建一个对象,这样如果对一个字符串对象进行频繁操作的时候,不会造成过多的内存浪费,其实本质上并没有很大区别,都是用来存储和操作字符串的,唯一的区别就在于性能上。
c. String主要用于公共 API,通用性好、用途广泛、读取性能高、占用内存小。
d. StringBuilder主要用于拼接 String,修改性能好。不过现在的编译器已经把String的 + 操作优化成 StringBuilder 了, 所以一般用String 就可以了。
e. String是不可变的,所以天然线程同步。
f. StringBuilder可变,非线程同步。
30、 C#函数 Func(string a, string b)用 Lambda 表达式怎么写?
(a,b) => {};
31、 数列1,1,2,3,5,8,13...第 n 位数是多少?用 C#递归算法实现
    
public int CountNumber ( int num ) { if ( num == 1 || num == 2 ) { return 1 ; } else { return CountNumber ( num - 1 ) + CountNumber ( num - 2 ) ; } }
32、 冒泡排序
    
public static void BubblingSort ( int [ ] array ) { for ( int i = 0 ; i < array . 长度 ; i ++ ) { for ( int j = array . 长度 - 1 ; j > 0 ; j -- ) { if ( array [ j ] < array [ i ] ) { int temp = array [ j ] ; array [ j ] = array [ j - 1 ] ; array [ j - 1 ] = temp ; } } } }
33、 C#中有哪些常用的容器类,各有什么特点?
容器类:List,HashTable,Dictionary,Stack,Queue
a. List:索引泛型容器 访问速度快 修改速度慢
b. HashTable/Dictionary:散列表格式 查询效率高 空间占用较大
c. Stack:后进先出
e. Queue:先进先出
34、 C#中常规容器和泛型容器有什么区别,哪种效率高?
不带泛型的容器需要装箱和拆箱操作速度慢,所以泛型容器效率更高数据类型更安全。
35、 有哪些常见的数值类?
简单值类型包括:整数类型、实数类型、字符类型、布尔类型
复合值类型包括:结构类型、枚举类型
36、 C#中委托和接口有什么区别?各自应用情况?
接口(interface)是约束类应该具备的功能集合,约束了类应该具备的功能,使类从千变万化的具体逻辑中解脱出来,便于类的管理和扩展,同时又合理解决了类的单继承问题。C#中的委托是约束方法集合的一个类,可以便捷的使用委托对这个方法集合进行操作。
使用接口应用情况:
a.无法使用继承的场合
b.完全抽象的场合
c.多人协作的场合
37、 C#中unsafe关键字是用来做什么的?什么场合下使用?
非托管代码才需要这个关键字一般用在带指针操作的场合
38、 C#中ref和out关键字有什么区别?
ref修饰参数,表示进行引用传递,out修饰参数也表示进行引用传递,但传递的引用只为带回返回值, ref又进又出,out不进只出。
39、 For,foreach,Enumerator.MoveNext的使用,与内存消耗情况?
for循环可以通过索引依次进行遍历,foreach和Enumerator.MoveNext通过迭代的方式进行遍历。内存消耗上本质上并没有太大的区别。但是在Unity中的Update中,一般不推荐使用foreach 因为会遗留内存垃圾。
40、 函数中多次使用string的+=处理,会产生大量内存垃圾(垃圾碎片),有什么好的方法可以解决?
通过StringBuilder那进行Append,这样可以减少内存垃圾
41、 当需要频繁创建使用某个对象时,有什么好的程序设计方案来节省内存?
设计单例模式进行创建对象或者使用对象池
42、 JIT和AOT区别?
JIT(Just-In-Time):实时编译,执行慢安装快占空间小一点。
AOT(Ahead-Of-Time ):预先编译,执行快安装慢占内存占外存大。
43、 给定一个存放参数的数组,重新排列数组。
void SortArray(Array arr){Array.Sort(arr);}
44、 Foreach循环迭代时,若把其中的某个元素删除,程序报错,怎么找到那个元素?以及具体怎么处理这种情况?(注:Try.....Catch捕捉异常,发送信息不可行)
Foreach不能进行元素的删除,因为迭代器会锁定迭代的集合,解决方法:记录找到索引或者Key值,迭代结束后再进行删除。
45、 GameObject a=new GameObject() GameObject b=a 实例化出来了A,将A赋给B,现在将B删除,问A还存在吗?
存在,b删除只是将它在栈中的内存删除,而A对象本身是在堆中,所以A还存在。
46、 C#中委托和事件的区别
委托是一个类,该类内部维护着一个字段,指向一个方法。事件可以被看作一个委托类型的变量,通过事件注册、取消多个委托或方法。以下分别通过委托和事件执行多个方法,从中体会两者的区别。
(1) 通过委托执行方法:在CLR运行时,委托DoSth实际上就一个类,该类有一个参数类型为方法的构造函数,并且提供了一个Invoke实例方法,用来触发委托的执行;委托DoSth定义了方法的参数和返回类型;通过委托DoSth的构造函数,可以把符合定义的方法赋值给委托;调用委托的实例方法Invoke执行了方法。
    
class Program { static void Main ( string [ ] args ) { Example example = new Example ( ) ; example . Go ( ) ; Console . ReadKey ( ) ; } } public class Example { public delegate void DoSth ( string str ) ; internal void Go ( ) { //声明一个委托变量,并把已知方法作为其构造函数的参数 DoSth d = new DoSth ( Print ) ; string str = "Hello,World" ; //通过委托的静态方法Invoke触发委托 d . Invoke ( str ) ; } void Print ( string str ) { Console . WriteLine ( str ) ; } }
(2) 委托变量(参数列表):委托DoSth的参数列表和方法Print的参数列表还是保持一致,委托DoSth中的参数object sender通常用来表示动作的发起者,EventArgs e用来表示动作所带的参数。
    
public class Example { public delegate void DoSth ( object sender , EventArgs e ) ; internal void Go ( ) { //声明一个委托变量,并把已知方法作为其构造函数的参数 DoSth d = new DoSth ( Print ) ; object sender = 10 ; EventArgs e = new EventArgs ( ) ; d ( sender , e ) ; } void Print ( object sender , EventArgs e ) { Console . WriteLine ( sender ) ; } }
(3) 通过事件执行方法:声明了事件myDoSth,事件的类型是DoSth这个委托;通过+=为事件注册委托;通过DoSth委托的构造函数为事件注册委托实例;采用委托变量(参数列表)这种形式,让事件执行方法。
    
public class Example { public delegate void DoSth ( object sender , EventArgs e ) ; public event DoSth myDoSth ; internal void Go ( ) { //声明一个委托变量,并把已知方法作为其构造函数的参数 DoSth d = new DoSth ( Print ) ; object sender = 10 ; EventArgs e = new EventArgs ( ) ; myDoSth += new DoSth ( d ) ; myDoSth ( sender , e ) ; } void Print ( object sender , EventArgs e ) { Console . WriteLine ( sender ) ; } }
(4) 通过+=还可以为事件注册多个委托。
    
public class Example { public delegate void DoSth ( object sender , EventArgs e ) ; public event DoSth myDoSth ; internal void Go ( ) { //声明一个委托变量,并把已知方法作为其构造函数的参数 DoSth d = new DoSth ( Print ) ; DoSth d1 = new DoSth ( Say ) ; object sender = 10 ; EventArgs e = new EventArgs ( ) ; //为事件注册多个委托 myDoSth += new DoSth ( d ) ; myDoSth += new DoSth ( d1 ) ; myDoSth ( sender , e ) ; } void Print ( object sender , EventArgs e ) { Console . WriteLine ( sender ) ; } void Say ( object sender , EventArgs e ) { Console . WriteLine ( sender ) ; } }
(5) 通过事件直接注册方法。
    
public class Example { public delegate void DoSth ( object sender , EventArgs e ) ; public event DoSth myDoSth ; internal void Go ( ) { object sender = 10 ; EventArgs e = new EventArgs ( ) ; //为事件注册多个委托 myDoSth += Print ; myDoSth += Say ; myDoSth ( sender , e ) ; } void Print ( object sender , EventArgs e ) { Console . WriteLine ( sender ) ; } void Say ( object sender , EventArgs e ) { Console . WriteLine ( sender ) ; } }
(6) 使用EventHandler来执行多个方法。
    
public class Example { public event EventHandler myEvent ; internal void Go ( ) { object sender = 10 ; EventArgs e = new EventArgs ( ) ; //为事件注册多个委托 myEvent += Print ; myEvent += Say ; myEvent ( sender , e ) ; } void Print ( object sender , EventArgs e ) { Console . WriteLine ( sender ) ; } void Say ( object sender , EventArgs e ) { Console . WriteLine ( sender ) ; } }
根据上述总结:
a. 委托就是一个类,也可以实例化,通过委托的构造函数来把方法赋值给委托实例
b. 触发委托有2种方式: 委托实例.Invoke(参数列表),委托实例(参数列表)
c. 事件可以看作是一个委托类型的变量
d. 通过+=为事件注册多个委托实例或多个方法
e. 通过-=为事件注销多个委托实例或多个方法
f. EventHandler就是一个委托
47、 空间内一物体绕球面固定点(0、1、2)按照固定速度speed环绕运动。
    
public float Speed = 1 ; void Update ( ) { transform . RotateAround ( new Vector3 ( 0 , 1 , 2 ) , Vector3 . up , Speed ) ; }
48、 用代码实现第三角色控制器
    
public class Player : MonoBehaviour { public Transform _cameraTrans ; private Vector3 _cameraOffset ; void Awake ( ) { _cameraOffset = transform . position - _cameraTrans . position ; } void Update ( ) { _cameraTrans . position = transform . position - _cameraOffset ; } }
49、 含义Mathf.Round, Mathf.Clamp, Mathf.Lerp?
Mathf.Round 四舍五入;Mathf.Clamp 限制;Mathf.Lerp 插值
50、 写一个计时器工具,从整点开始计时,格式为:00:00:00
    
private float timer = 0f ; private int h = 0 ; private int m = 0 ; private int s = 0 ; private string timeStr = string . Empty ; void Update ( ) { timer += Time . deltaTime ; if ( timer >= 1f ) { s ++ ; timer = 0 ; } if ( s >= 60 ) { m ++ ; s = 0 ; } if ( m >= 60 ) { h ++ ; m = 0 ; } if ( h >= 99 ) { h = 0 ; } } void OnGUI ( ) { timeStr = string . Format ( "{0:D2}:{1:D2}:{2:D2}" , h , m , s ) ; GUI . Label ( new Rect ( 10 , 10 , 100 , 200 ) , timeStr ) ; }
51、 用鼠标实现在场景中拖动物体,用鼠标滚轮实现缩放(用一个Cube 即可)。
在场景中添加一个Plan,Camera,Directional Light,Cube。添加两个脚本scrollerScirpt(挂在Camera),CubeDragScript(挂在Cube上)。
a.鼠标滚轮实现缩放:将摄像机的镜头拉近或者拉远,调整摄像机的视角就可以实现,主要实现代码如下:
    
void Update ( ) { //鼠标滚轮的效果 if ( Input . GetAxis ( "Mouse ScrollWheel" ) < 0 ) { if ( Camera . main . fieldOfView <= 100 ) Camera . main . fieldOfView += 2 ; if ( Camera . main . orthographicSize <= 20 ) Camera . main . orthographicSize += 0.5F ; } //Zoom in if ( Input . GetAxis ( "Mouse ScrollWheel" ) > 0 ) { if ( Camera . main . fieldOfView > 2 ) Camera . main . fieldOfView -= 2 ; if ( Camera . main . orthographicSize >= 1 ) Camera . main . orthographicSize -= 0.5F ; } }
b.鼠标实现在场景中拖动物体:
  解决思路就是将世界坐标转换成屏幕坐标,然后计算物体与鼠标之间移动量,循环鼠标被按下操作,得到鼠标的当前位置,加上计算好的移动量,将新的坐标赋值给物理就行了。主要是开启一个协同程序(Corountine)来处理。主要代码如下:
    
// Use this for initialization void Start ( ) { StartCoroutine ( OnMouseDown ( ) ) ; } IEnumerator OnMouseDown ( ) { //将物体由世界坐标系转换为屏幕坐标系 Vector3 screenSpace = Camera . main . WorldToScreenPoint ( transform . position ) ; //完成两个步骤 1.由于鼠标的坐标系是2维,需要转换成3维的世界坐标系 //2.只有3维坐标情况下才能来计算鼠标位置与物理的距离,offset即是距离 //将鼠标屏幕坐标转为三维坐标,再算出物体位置与鼠标之间的距离 Vector3 offset = transform . position - Camera . main . ScreenToWorldPoint ( new Vector3 ( Input . mousePosition . x , Input . mousePosition . y , screenSpace . z ) ) ; while ( Input . GetMouseButton ( 0 ) ) { //得到现在鼠标的2维坐标系位置 Vector3 curScreenSpace = new Vector3 ( Input . mousePosition . x , Input . mousePosition . y , screenSpace . z ) ; //将当前鼠标的2维位置转换成3维位置,再加上鼠标的移动量 Vector3 curPosition = Camera . main . ScreenToWorldPoint ( curScreenSpace ) + offset ; //curPosition就是物体应该的移动向量赋给transform的position属性 transform . position = curPosition ; yield return new WaitForFixedUpdate ( ) ; //这个很重要,循环执行 } }
52、 NGUI Button 怎样接受用户点击并调用函数,具体方法名称是什么?
a. 主要是在UICamera脚本中用射线判断点击的物体并通过SendMessage调用OnClick() OnPress()等函数,可以说NGUI的按钮是通过发消息这个方式调用的。具体方法名称是OnClick()。
b. 事例代码:
    
void Awake ( ) { //获取需要监听的按钮对象 GameObject button = GameObject . Find ( "UI Root/Button3" ) ; //设置这个按钮的监听,指向本类的ButtonClick方法中。 UIEventListener . Get ( button ) . onClick = OnButton3Click ; } private void OnButton3Click ( GameObject button ) { Debug . Log ( "我是按钮3被点击了" ) ; }
53、 itween 插件的作用是什么,itween 作用于世界坐标还是局部坐标,请列举出 3 个其常用方法?
iTween 是一个动画库,作者创建它的目的就是最小的投入实现最大的产出。让你做开发更轻松,用它可以轻松实现各种动画,晃动,旋转,移动,褪色,上色,控制音频等等方法:
a. MoveTo 物体移动;
b.ColorTo:随着时间改变对象的颜色组;
c. LookTo:随时间旋转物体让其脸部朝向所提供的 Vector3 或 Transform 位置;
54、 去掉敏感字的程序
    
String s = "你是坏蛋" ; s . Replace ( "坏蛋" , "**" ) ;
55、 写一个角色控制器,鼠标控制屏幕晃动,鼠标控制开枪。
    
public class Player : MonoBehaviour { public GameObject _prefabBullet ; private float _angleSpeed = 120f ; void Update ( ) { float eularY = Input . GetAxis ( "Mouse X" ) * _angleSpeed * Time . deltaTime ; transform . Rotate ( new Vector3 ( 0 , eularY , 0 ) ) ; if ( Input . GetMouseButtonDown ( 0 ) ) { Instantiate ( _prefabBullet , transform . position , transform . rotation ) ; } }
56、 需求:写一个角色控制器,鼠标控制屏幕晃动,鼠标控制开枪。敌人AI,有各种状态,实现各种状态之间的切换。敌人会和主角对抗,敌人被打到之后,会闪一次红色,然后红色比例提升10%,10次攻击之后,成红色。敌人会自动攻击主角,主角也会有颜色变化。敌人会在范围内巡逻。UI,左边显示8个AI的被攻击次数,右边显示AI的攻击次数排序。
    
public class Player : MonoBehaviour { public Camera _camera ; public GameObject _prefabBullet ; private float _angleSpeed = 120f ; //生命值 private int _life = 10 ; //玩家的状态 private bool _state = false ; //是否被打到 public void IsState ( ) { if ( _state && _life > 0 ) { _life -= 1 ; _state = false ; } else { _state = true ; } } public void RoleRotate ( ) { float eularY = Input . GetAxis ( "Mouse X" ) * _angleSpeed * Time . deltaTime ; } //风发射子弹 public void RoleShoot ( ) { if ( Input . GetMouseButtonDown ( 0 ) ) { Instantiate ( _prefabBullet , transform . position , transform . rotation ) ; } } } public class Enemy : MonoBehaviour { //敌人被打到状态 private bool _state = false ; //玩家与敌人距离 private float _distance ; //角色 public GameObject _role ; //生命值 private int _life = 10 ; //敌人被攻击次数 private int _timeAccack = 0 ; //敌人状态 public void EnemyState ( ) { if ( _distance >= 10f ) { if ( _life >= 1 && _state == true ) { _life -= 1 ; _timeAccack ++ ; } _state = false ; } else if ( _distance >= 0 && _state == false ) { _state = true ; } } //敌人与玩家距离 public void Distance ( ) { _distance = Vector3 . Distance ( transform . position , _role . transform . position ) ; } void OnGUI ( ) { GUI . TextArea ( new Rect ( 20 , 50 , 80 , 30 ) , _timeAccack . ToString ( ) ) ; GUI . TextArea ( new Rect ( 20 , 90 , 80 , 30 ) , _timeAccack . ToString ( ) ) ; GUI . TextArea ( new Rect ( 20 , 130 , 80 , 30 ) , _timeAccack . ToString ( ) ) ; } }
57、 3D空间有三个cube当做点,有一条鱼的模型,要求在三点之间游动,要求转向平滑一点,控制鱼的运动朝向(用四元数和欧拉角)
使用transform.localRotation = Quaternion.Slerp(Quaternion a,Quaternion b,float c)实现物体平滑转向。
Unity3d Android SDK接入解析(二)Unity3d Android SDK的设计与两种接入方式 上篇说清楚了Unity和Android调用的方式,很多东西没有讲很详细,因为重头在这篇,讲的是怎么具体接入Android SDK的方式,和怎么自己去做一个方便Unity接入的SDK。 如果你跟着我做完了,你应该理解到的内容: 1. 正确的完成一个方便Unity接入的SDK 2. 使用导出工程的模式完成SDK的接入 3. 使用Unity插件的形式进行Android的接入 阅读详情

相关推荐

World Machine大地形导出成分块地形(tile瓷块导出,包括高度图+贴图)到unity3d2017

上次介绍了如何把真实地形数据DEM导入world machine制作地形,博客地址:https://blog.youkuaiyun.com/qq_29413829/article/details/80631891 。这次也是因为项目需要,讲一下World Machine大地形导出成分块地形,导入unity3D2017。因为之前也没看到world Machine怎么导出分块地形,花了两天找资料,琢磨,最后偶然搞...

一个渣渣的世界博客 1万+

Unity3D 实用技巧 - 基础知识大全集(三)

上一篇:Unity3D 实用技巧 - 基础知识大全集(二)Part2:算法类1、常用的数据结构。数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成 。 常用的数据结构有:数组,栈,链表,队列,树,图,堆,散列表等。2、数组理解数组是可以再内存中连续存储多个元素的结构,在内存中的分配也是连续的,数组中的元素通过数组下标进行访问,数组下标从0开始。例如下面这段代码...

unityofficial的博客 178

Unity3D 实用技巧 - 从实践中总结经验(1)

本文转自 Unity Connect 博主 北京琳云信息科技有限责任公司 巧用 Unity3D 引擎编辑器 作为一名游戏开发者,学会巧用引擎编辑器,可以让我们创造出更多优秀的游戏作品。今天小编与大家共同浅析这些常见的实用技巧。 活用 Unity3D 引擎编辑器技巧 1、通过 Assets 分支保证正确的流程 所有的 Asset 都应该只有一个唯一的版本。如果当我们需要一个分支版本的 Prefab、...

优快云_ONION的博客 648

Unity3D 实用技巧 - 基础知识大全集(四)

上一篇:Unity3D 实用技巧 - 基础知识大全集(三)Part5: 案例类1、《愤怒的小鸟》给予初速度以后,怎么让小鸟受到重力和空气阻力的影响而绘制抛物线轨迹,说出具体的计算方法。Vector3 v 代表初速度 v'代表现在的速度, 假设小鸟是沿的 z 轴也就是 transform.forward方向运动的质量为 1,那么 v'=v-new Vector3(0,gt,ft),transform...

unityofficial的博客 88

【Unity3D】二、制作滚球游戏学习Unity3D(上)

从创建项目开始 创建一个项目 打开unity,在Projects中可以查看当前的本地项目或者云端项目,点击New project或者右上角的New都可以新建项目。 然后在1处填写创建项目的名称,2处选择创建地址,3处选择Template(模板),可以选中3D或者2D。 稍等片刻即可进入unity的主页面。 保存Scene并管理Assets 进入unity之后,可以看到已经预设的SampleSc...

超级超级小天才的博客 3479

Unity3D 实用技巧 - 快速学会模型合理导入 Unity3D 引擎

本文转自Unity Connect博主 北京琳云信息科技有限责任公司 学习模型合理导入 Unity3D 引擎 相信在游戏中,模型相当于游戏必要的元素,例如游戏的一个人物角色,我们可以称它为一个模型,今天和小编一起学习一下,导入 Unity 3d 模型,我们应该注意哪些细节!当然我们知道常用的模型都可以通过 Maya/3D Max 等三维动画软件制作的。 官方学习文档:https://do...

优快云_ONION的博客 1486

Unity3D 实用技巧 - 基础知识大全集(一)

小编良久没有分享了,今天就和大家回览一下Unity3d基础的知识点哈!虽然网上也有很多基础知识点的文章内容,但是相信汇总起来,有空回览一番也是别有意义的。初阶内容Part1:Unity 编辑器相关类1、Unity 界面视图窗口,主要包括工具栏、状态栏、Project窗口、Hierarchy窗口、Scene窗口、Game窗口、Inspector 窗口。官方链接:https://docs.unity3...

unityofficial的博客 1160

Unity3d接入googleplay内购详细说明(二)

Unity3d接入googleplay内购详细说明(一) 引言 一、准备条件: 二、谷歌开发者后台应用创建说明: Unity3d接入googleplay内购详细说明(二) 三、Unity3d向安卓通信以及接受通信 四、Unity导出安卓Apk正式签名说明 五、使用Eclipse运行unity导出的工程 六、Java代码接入谷歌内购: 七、谷歌内购Java代码 Unity3d接入googleplay内购详细说明(三) 八、Apk上传谷歌商店测试版以及添加测试者 九、Zipalign处理APK文件 十、添加

三人行、则必有我师 1万+

【Unity3D】基础知识学习笔记

Unity3D基础知识学习笔记 1、基础知识: 标题栏 菜单栏 工具栏:变换工具、gizmos切换、播放控件、层列表、布局列表 功能窗口 2、资源及资源类型:在project里面能够create的资源。project面板可以对资源进行组织管理,创建资源,搜索资源。 3、模型和角色动画: maya、3dmax创建的模型、动画,用插件输出(fbx、obj)或者软件自己的格式(m

活到老,学到老! 1万+

unity3d基础开发地形的基础知识

unity3d基础开发地形的基础知识 (0)基本术语 Splat:地形所使用的贴图,即Terrain Texture。术语叫Splat或者 Splat map。 Splat Alhpa Map:地形贴图布局图,unity3d论坛用图的rgba各个通道来表示贴图在地形上的使用,project界面里展开地形即可看见。术语叫Splat Alpha Map,或者Alpha Map. (1)地形

u013951435的专栏 2483

Unity3D中的shader渲染通道基础知识

1.Unity中配备了强大的阴影和材料的语言工具称为ShaderLab,以程式语言来看,它类似于CgFX和Direct3D的效果框架语法,它描述了材质所必须要的一切咨询,而不仅仅局限于平面顶点/像素着色。 2.在Unity3D中创建一个Shader:Assets -> Create -> Shader 3.创建了Shader就可以应用到各个材质Material中,创建材质:As

unity3d,unity3d教程下载 3652

Unity3D基础知识梳理<转>

这段时间在做Unity的项目,这差不多是我的第一次实战啊~然后公司来了实习的童鞋要学Unity,但是我一向不靠谱啊,所以只能帮他们稍微梳理下基础的东西了啊,唉~学长只能帮你们到这里了~顺便就把自己这两天整理的一些基础知识分享上来了,闲话不多说~ 美术部分:        Unity的话主要还是分两块吧,第一块是美术(自己都不懂~这里允许我稍微带过一下吧~),美术的话主要包括3d模型、材

御剑江湖的专栏 4981

C# Unity3D科目二模拟驾考软件源码实现

C#(读作”See Sharp”)是一种简单、现代、面向对象的编程语言。自2000年推出以来,它已成为.NET平台的核心语言,广泛用于开发Windows应用程序、Web服务、游戏开发以及其他多种应用程序。Unity3D引擎的历史可以追溯到2004年,当时它被设计为名为“游戏动力”(Gamebryo Lightspeed)的游戏开发工具。2005年,Unity Technologies收购了这款游戏引擎,并在2007年发布了第一个版本。

weixin_42300144的博客 1035

【Unity3D】Unity3D学习笔记

C#学习笔记

qq_44951699的博客 4800

工业相机与ABB机器人Socket通信实战:手把手教你用RobotStudio 6.08搭建视觉引导工作站

本文详细介绍了工业相机与ABB机器人通过Socket通信实现视觉引导工作站的实战教程。使用RobotStudio 6.08平台,涵盖工作站搭建、坐标系标定、RAPID代码开发及TCP/IP通信配置,特别解析了欧拉角与四元数转换等关键技术难点,助力智能制造产线升级。

weixin_42531516的博客 407

LightGBM处理类别特征和缺失值有多省心?一个真实业务数据案例带你上手

本文通过真实电商数据案例,详细解析了LightGBM如何高效处理类别特征和缺失值。相比传统方法,LightGBM仅需一行代码即可自动处理高基数类别特征和缺失值,大幅提升模型训练效率和预测准确度,特别适合业务场景中的脏数据处理。

weixin_30689307的博客 460

知识记录:Unity3D 实用技巧 - 基础知识汇总【小白篇】

#关注公众知享奇,获取更多资源 我的博客 博客地址 1、Unity中的碰撞器和触发器的区别? 碰撞器是触发器的载体,而触发器只是碰撞器身上的一个属性。当Is Trigger=false时,碰撞器根据物理引擎引发碰撞,产生碰撞的效果,可以调用OnCollisionEnter/Stay/Exit函数;当Is Trigger=true时,碰撞器被物理引擎所忽略,没有碰撞效果,可以调用OnTriggerEnter/Stay/Exit函数。如果既要检测到物体的接触又不想让碰撞检测影响物体移动或要检测一个物件是否经

qq_42555291的博客 1086

python cartopy绘制扇形区域图/cartopy绘制北极部分区域

实际上,这个问题原因还是由于投影转换的问题,在set_extend时,绘制的上下边界仍然是方形、未被正确投影的边界,与我们的set_boundary存在冲突,最根本的原因还是在于cartopy对于投影计算的一些缺陷。另外我们需要指出的是:**该方法不适用于极地投影,即NorthPolarStereo,由于NorthPolarStereo本身投影特性只需一个参数,本身并不适合。我们绘制极地投影时,同样也是使用set_boundary绘制圆形边界,那么当我们想要绘制扇形时,可以通过。请根据喜好自行选择,

weixin_43750300的博客 3212

Unity3D基础知识——遍历子物体

Unity3D基础知识——遍历子物体 目录 1、博客介绍 2、内容 (1)遍历子物体 (2)遍历子孙物体 (3)筛选遍历 3、推送 4、结语 1、博客介绍 本篇将记录基础知识遍历某物体的子物体或者遍历子物体以及孙物体,或者筛选遍历 2、内容 (1)遍历子物体 (该方法之遍历子物体,不涉及孙物体) ...

孙君的空间站 3558

适航规章、标准,书籍资料下载汇总(增加DO-297 IMA)

从事IMA平台适航工作的朋友看过来,DO-297英文版PDF可以下载了!更新日志:2024-9-28:初版。2024-10-21:增加DO-330英文版PDF下载,后台回复关键词”330“获取下载链接。2024-10-30:增加DO-160G中文版(非机翻)和英文版PDF下载,后台回复关键词”160“获取下载链接。2024-11-10:增加DO-297英文版PDF下载,后台回复关键词”297“获取下载链接。以下是一些收集到的适航相关的资料,分享给大家。

qq_41854911的博客 1577

YOLOv11涨点改进| CVPR 2026 |独家创新首发、特征融合改进篇| 引入FAAFusion傅里叶角对准融合模块,促进高低频特征融合,增强模型在小目标、密集目标检测和旋转目标检测任务高效涨点

🔥本文提出FAAFusion傅里叶角对准融合模块,用于改进YOLOv11网络模型。该模块通过在特征金字塔融合阶段对齐高低层特征的方向信息,缓解传统FPN直接融合带来的方向冲突问题。FAAFusion利用傅里叶旋转等变性原理,在频域估计主方向并进行特征对齐,显著提升了多尺度特征表达的一致性与有效性。实验表明,该方法在DOTA等遥感数据集上取得了新的最先进水平,特别适用于旋转目标检测任务。文章详细介绍了模块原理、结构优势,并提供了三种不同的YOLOv11改进配置方案和完整的核心代码实现。

Ai缝合怪、助力小伙伴高效发论文 152

Unity3D基础知识笔记

Unity是由Unity Technologies公司开发的跨平台专业游戏引擎,具有一个完美的游戏开发生态链。

lolly114的博客 826

2026年全国青少年信息素养大赛复赛真题(算法应用主题赛C++小学组:带解析)(7月4日试卷一)【文末附答案和解析】

2026年全国青少年信息素养大赛复赛真题(算法应用主题赛C++小学组:带解析)(7月4日试卷一)【文末附答案和解析】

王老师青少年编程 1737

Unity3D教程使用小技巧大合集

1、Crtl+f摄像机自动适配场景。 2、可以用一个立方体作为底盘。 3、人物角色可以直接引入包,有第一人称和第三人称,已经封装好。 4、光源可以设置投影。 5、3DMax是Z轴向上,而一般游戏引擎是Y轴向上,所以导出的时候一定要注意选择YZ转化的格式(YZ转化选项一定要勾选)。 另外,obj格式不支持动画,其实游戏中最常用的格式是“FBX”和“DAE”格式,“FBX”最常用,注意导出动

unity3d,unity3d教程下载 896

Windows10环境下激活虚拟环境报错【source : 无法将“source”项识别为 cmdlet、函数、脚本文件或可运行程序的名称】

在使用Django创建Web程序前,需要创建一个虚拟的工作环境,在使用【source ll_env/bin/activate】命令激活虚拟环境时报错:source : 无法将“source”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。所在位置 行:1 字符: 2。

提供C#相关开发 、云计算、运维测试、网络安全相关技术分享与服务,有意向可联系。 1万+

linux安装配置Mysql详细步骤

下载Mysql rpm包 官网下载:https://dev.mysql.com/downloads/mysql/ 如果你到了这里,本地应该有了如下四个rpm包: mysql-community-client-5.7.26-1.el6.x86_64.rpm mysql-community-common-5.7.26-1.el6.x86_64.rpm mysql-community-libs-5...

🏆 前端领域优质创作者 7万+
上一篇: 【入门】HDRP游戏运行后,看不到运动物体
下一篇: Unity3D 实用技巧 - 基础知识大全集(四)
Unity官方开发者社区
博客等级 码龄3年 597粉丝 752原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值