赞
踩
static class adsa {}静态类中为可实例出对象的类添加方法——>拓展方法
两个不同的游戏物体里通过同一个脚本访问的静态变量是同一个。静态变量是属于类的,而不是属于类的任何特定实例。unity中也是如此。
- using UnityEngine;
-
- public class MyScript : MonoBehaviour
- {
- public static int staticVar = 0;
-
- static MyScript()
- {
- Debug.Log("Static constructor called.");
- }
-
- void Start()
- {
- staticVar++;
- Debug.Log($"Instance started. StaticVar is now: {staticVar}");
- }
- }

c#中的///:注释说明下方的数据或者函数是干嘛的
C#的内存回收:GC.Collect()、一代二代三代...
堆栈的内存关系主要体现在它们各自在内存中的使用方式、特点以及它们之间的区别上。堆栈通常指的是栈(Stack)和堆(Heap)这两个内存区域,它们都是程序在运行时用于存储数据的内存部分,但各有其特性和用途。
特性 | 栈(Stack) | 堆(Heap) |
---|---|---|
管理方式 | 自动管理(编译器) | 手动管理(程序员) |
分配方式 | 静态分配(编译时确定) | 动态分配(运行时确定) |
存储内容 | 局部变量、函数调用信息 | 对象、数组等复杂数据结构 |
访问速度 | 快(连续内存块) | 相对较慢(可能不连续) |
内存大小 | 有限制(如1MB) | 几乎无限制(受物理内存和操作系统限制) |
内存释放 | 自动释放(函数返回或作用域结束) | 手动释放(程序员调用释放函数) |
new的东西的内存实实在在的在堆上,栈上只是你引用的把玩。
在C#中,堆栈关系与在其他编程语言中的概念大致相同,但具体到类的实例化时,有一些细节需要注意。当你实例化一个Person
类时,这个实例的内存分配和堆栈的关系主要体现在以下方面:
Person
类的一个实例时(例如,使用new Person()
),这个实例的内存是在堆上分配的。堆是用于存储对象实例的内存区域,它允许动态的内存分配和释放。Person
类的实例并将其赋值给一个局部变量时,这个局部变量(实际上是一个引用)是存储在栈上的。Person
实例的内存地址(或引用)。通过这个引用,你可以访问堆上的Person
实例。Person
实例的引用)会被自动销毁(或说其作用域结束),但这并不影响堆上的Person
实例。堆上的实例会继续存在,直到没有任何引用指向它,此时垃圾回收器会在未来的某个时间点回收它所占用的内存。- class Person
- {
- public string Name { get; set; }
-
- public Person(string name)
- {
- Name = name;
- }
- }
-
- class Program
- {
- static void Main(string[] args)
- {
- // 局部变量personRef是存储在栈上的,它保存了对堆上Person实例的引用
- Person personRef = new Person("Alice");
-
- // 使用personRef来访问堆上的Person实例
- Console.WriteLine(personRef.Name); // 输出: Alice
-
- // 当Main方法执行完毕时,personRef局部变量会被销毁(或说其作用域结束)
- // 但堆上的Person实例("Alice")仍然存在,直到垃圾回收器回收它
- }
- }

在C#中,当你实例化一个类(如Person
)时,实例本身是在堆上分配的,而指向这个实例的引用(通常是一个局部变量)是存储在栈上的。这种堆栈关系允许你动态地管理内存,并通过引用访问堆上的对象实例。然而,需要注意的是,程序员通常不需要(也不应该)直接管理堆上的内存分配和释放,这是由.NET运行时的垃圾回收机制自动完成的。
性能考虑:Unity和C#都鼓励使用托管资源,并通过垃圾回收器自动管理内存。析构函数(作为终结器)的调用时机是不确定的,依赖于垃圾回收器的运行,这可能导致性能问题或不可预测的行为。
资源管理:对于Unity游戏开发,资源管理通常通过其他机制进行,如MonoBehaviour的生命周期方法(如Start、Update、OnDestroy等)来管理游戏对象的行为和生命周期。
推荐使用Dispose模式:对于需要显式释放资源的类(如包含非托管资源的类),C#建议使用IDisposable接口和Dispose方法,而不是析构函数。这样,调用者可以显式地调用Dispose方法来释放资源,或者将对象包装在using语句中自动调用Dispose。
在C#中,{0}
, {1}
等是字符串格式化时使用的占位符,它们属于复合格式化功能的一部分。这种格式化方式允许你在字符串中嵌入一个或多个占位符,然后在调用字符串的 Format
方法或使用字符串插值(从C# 6.0开始引入)时,用实际的值来替换这些占位符。
String.Format
在较老的C#版本中,String.Format
方法是常用的字符串格式化方式。这个方法接受一个格式字符串和一系列与格式字符串中的占位符相对应的值。
string name = "Alice"; | |
int age = 30; | |
string greeting = String.Format("Hello, {0}! You are {1} years old.", name, age); | |
Console.WriteLine(greeting); // 输出: Hello, Alice! You are 30 years old. |
在这个例子中,{0}
被 name
变量的值 "Alice"
替换,{1}
被 age
变量的值 30
替换。
从C# 6.0开始,引入了字符串插值作为更简洁、更易读的字符串格式化方式。字符串插值允许你在字符串字面量中直接嵌入表达式,这些表达式的值将在运行时被计算并插入到字符串中。
string name = "Alice"; | |
int age = 30; | |
string greeting = $"Hello, {name}! You are {age} years old."; | |
Console.WriteLine(greeting); // 输出: Hello, Alice! You are 30 years old. |
在这个例子中,{name}
和 {age}
是被嵌入的表达式,它们将分别被 name
和 age
变量的值替换。
总的来说就是,class这类引用类型只有new了才会开一片内存,同个class的个体相互赋值,赋的是引用的能力。
所以在unity中,我们可以发现,写了一个新script,class里面,public 某某东西a,我们只要find出来b或者拖上去,这个就可以代表被拖的那个物体b,去动b的各种组件,甚至把b当做新的出发点,去进行某些操作。
default(类型名)得到默认值
引用类型(如类)的默认值是null
,而值类型(如int、float、结构体等)的默认值是它们类型的默认值(不是null
)
所以class中可以声明自己,因为是引用类型,默认为NULL(绝对不能实例初始),但结构体不行,会无限循环
C#中的枚举(Enum)是一种特殊的值类型,它用于声明一组命名的整型常量。枚举类型使用enum
关键字来声明。枚举提供了一种类型安全的方式来使用一组预定义的常量。
enum EnumName | |
{ | |
Value1, | |
Value2, | |
// 可以根据需要添加更多值 | |
ValueN | |
} |
EnumName
是枚举类型的名称。Value1
, Value2
, ..., ValueN
是枚举的成员,它们都是整数值,默认从0开始递增。你也可以为枚举成员指定整数值(包括负数或十六进制数)。
enum Days | |
{ | |
Sunday = 1, | |
Monday, | |
Tuesday, | |
Wednesday, | |
Thursday, | |
Friday, | |
Saturday = 0 // 可以显式地将一个枚举成员的值设置为0 | |
} | |
// 或者直接使用十六进制 | |
enum Colors : ushort | |
{ | |
Red = 0x0001, | |
Green = 0x0002, | |
Blue = 0x0004 | |
} |
注意:
Colors
枚举中,: ushort
指定了枚举的底层类型为ushort
。默认情况下,枚举的底层类型是int
。你也可以将其指定为byte
、sbyte
、short
、ushort
、int
、uint
、long
或ulong
。枚举的使用非常简单,就像使用其他整型变量一样。
Days today = Days.Monday; | |
Console.WriteLine((int)today); // 输出:2 | |
Colors myColor = Colors.Red; | |
Console.WriteLine((ushort)myColor); // 输出:1 |
注意,当需要将枚举值转换为整数时,需要显式地进行类型转换(如上例所示)。
由于枚举本质上是一个整数值的集合,所以不能直接遍历。但是,你可以通过Enum.GetNames
或Enum.GetValues
方法来获取枚举的所有名称或值,并进行遍历。
foreach (string name in Enum.GetNames(typeof(Days))) | |
{ | |
Console.WriteLine(name); | |
} | |
// 或者遍历枚举值 | |
foreach (Days day in Enum.GetValues(typeof(Days))) | |
{ | |
Console.WriteLine(day); | |
} |
这样,你就可以在C#中灵活地使用枚举来管理一组相关的常量了。
在Unity中,接口的应用可以简单概括为一种约束,让复杂的各种人物动物先接上接口,接口有什么功能就都要补上,而接口作为一个类,出bug了也好找上是什么函数有问题。
对于逻辑的清晰和条理,作用是极大的。
以下是一个简化的例子来说明接口在Unity中的应用:
假设我们正在开发一个包含多种角色的游戏,这些角色虽然外观和技能各不相同,但都需要实现移动功能。我们可以定义一个名为IMovable
的接口,来规定所有可移动角色必须实现的方法。
IMovable接口定义:
public interface IMovable | |
{ | |
void Move(Vector3 direction, float speed); | |
} |
这个接口定义了一个Move
方法,它接收两个参数:一个是移动方向(Vector3
类型),另一个是移动速度(float
类型)。任何想要实现移动功能的类都需要实现这个接口,并提供Move
方法的具体实现。
角色类实现IMovable接口:
接下来,我们可以创建一个角色类(比如Player
类)来实现这个接口。
csharp复制代码
public class Player : MonoBehaviour, IMovable | |
{ | |
public void Move(Vector3 direction, float speed) | |
{ | |
// 实现移动逻辑,比如使用Rigidbody组件来移动 | |
transform.position += direction * speed * Time.deltaTime; | |
} | |
// 其他角色相关的属性和方法... | |
} |
在上面的例子中,Player
类通过实现IMovable
接口,承诺了会提供一个Move
方法。这样,无论游戏中有多少个不同的角色类,只要它们实现了IMovable
接口,我们就可以用相同的方式来处理它们的移动逻辑,而不需要关心它们内部的具体实现细节。
在Unity游戏中,接口的应用远不止于此,它们可以用于实现各种游戏逻辑和功能,帮助开发者构建更加灵活和可维护的游戏系统。
API(Application Programming Interface,应用程序编程接口)
并不仅仅是指类,API更广泛地定义为一组协议、规范或工具,它们为软件应用程序(包括Web服务、操作系统、数据库系统等)之间的交互提供了明确的方法和约定。
API可以包含多种元素,包括但不限于:
函数:在面向对象编程中,这通常表现为类的方法或静态函数。但在其他编程范式中,API也可以仅仅是一组可以调用的函数。
类:在面向对象的语言中,类本身就可以作为API的一部分,因为它们封装了数据和方法,提供了与对象交互的接口。
数据类型:API还可以定义特定的数据类型,这些数据类型用于在API的调用中传递和接收数据。
协议:在网络编程中,API可能定义了一种或多种通信协议,这些协议规定了客户端和服务器之间如何交换数据。
规范:API规范文档详细说明了如何使用API,包括它提供的函数、类、数据类型、协议以及任何必要的调用参数、返回值和错误处理机制。
库:有时,API会以库的形式提供,这些库包含了实现API所需的所有类和函数,开发者可以通过包含这些库来在自己的应用程序中使用API。
Web服务:在现代Web开发中,API经常以Web服务的形式出现,这些服务通过HTTP请求和响应来提供数据和功能。
Time.time
(表示从游戏开始到现在的时间)、Time.deltaTime
(表示上一帧到当前帧的时间间隔)等。Mathf
类中的Abs
(绝对值)、Pow
(幂运算)等,以及Vector3
、Quaternion
等类,用于处理向量和四元数运算。Start
、Update
、FixedUpdate
、LateUpdate
等,它们在游戏的生命周期中按特定顺序被调用,允许开发者在这些时间点执行特定的代码。Awake
、OnEnable
、OnDisable
、OnDestroy
等,它们在GameObject或组件的生命周期中被调用。Debug.Log
、Debug.LogWarning
、Debug.LogError
等,帮助开发者在开发过程中跟踪和解决问题。总的来说,Unity中的API是开发者在游戏开发过程中不可或缺的工具,它们为开发者提供了丰富的功能和灵活的接口,使得游戏开发变得更加高效和便捷。通过熟练掌握和使用这些API,开发者可以创建出更加复杂和精彩的游戏作品。
Getcomponent同样是没找到就返回NULL
- using UnityEngine;
-
- public class FindGameObjectExample : MonoBehaviour
- {
- void Start()
- {
- // 尝试查找名为"MyGameObject"的GameObject
- GameObject myGameObject = GameObject.Find("MyGameObject");
-
- // 检查是否找到了GameObject
- if (myGameObject != null)
- {
- // 如果找到了,打印消息
- Debug.Log("找到了名为'MyGameObject'的GameObject");
- // 这里可以添加更多处理找到的GameObject的代码
- }
- else
- {
- // 如果没有找到,打印消息
- Debug.Log("没有找到名为'MyGameObject'的GameObject");
- // 这里可以添加处理未找到GameObject的代码
- }
- }
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。