unity和c#的问题记录(1)

杂记

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)几乎无限制(受物理内存和操作系统限制)
内存释放自动释放(函数返回或作用域结束)手动释放(程序员调用释放函数)

c#中的例子

new的东西的内存实实在在的在堆上,栈上只是你引用的把玩。

在C#中,堆栈关系与在其他编程语言中的概念大致相同,但具体到类的实例化时,有一些细节需要注意。当你实例化一个Person类时,这个实例的内存分配和堆栈的关系主要体现在以下方面:

堆(Heap)

  • 当你在C#中创建Person类的一个实例时(例如,使用new Person()),这个实例的内存是在堆上分配的。堆是用于存储对象实例的内存区域,它允许动态的内存分配和释放。
  • 堆上的内存分配是由.NET运行时(CLR)管理的,它使用垃圾回收(Garbage Collection, GC)机制来自动释放不再使用的内存

栈(Stack)

  • 栈在这里主要涉及到的是局部变量和函数调用的上下文。当你在方法中创建一个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中不常使用析构函数?

性能考虑:Unity和C#都鼓励使用托管资源,并通过垃圾回收器自动管理内存。析构函数(作为终结器)的调用时机是不确定的,依赖于垃圾回收器的运行,这可能导致性能问题或不可预测的行为。
资源管理:对于Unity游戏开发,资源管理通常通过其他机制进行,如MonoBehaviour的生命周期方法(如Start、Update、OnDestroy等)来管理游戏对象的行为和生命周期
推荐使用Dispose模式:对于需要显式释放资源的类(如包含非托管资源的类),C#建议使用IDisposable接口和Dispose方法,而不是析构函数。这样,调用者可以显式地调用Dispose方法来释放资源,或者将对象包装在using语句中自动调用Dispose。

c#字符串相关操作

在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 及更高版本)

从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 变量的值替换。

C#中引用类型、值类型

总的来说就是,class这类引用类型只有new了才会开一片内存,同个class的个体相互赋值,赋的是引用的能力。

所以在unity中,我们可以发现,写了一个新script,class里面,public 某某东西a,我们只要find出来b或者拖上去,这个就可以代表被拖的那个物体b,去动b的各种组件,甚至把b当做新的出发点,去进行某些操作。

default(类型名)得到默认值

引用类型(如类)的默认值是null,而值类型(如int、float、结构体等)的默认值是它们类型的默认值(不是null

所以class中可以声明自己,因为是引用类型,默认为NULL(绝对不能实例初始),但结构体不行,会无限循环

c#枚举语法

C#中的枚举(Enum)是一种特殊的值类型,它用于声明一组命名的整型常量。枚举类型使用enum关键字来声明。枚举提供了一种类型安全的方式来使用一组预定义的常量。

基本语法

enum EnumName
{
Value1,
Value2,
// 可以根据需要添加更多值
ValueN
}
  • EnumName 是枚举类型的名称。
  • Value1Value2, ..., ValueN 是枚举的成员,它们都是整数值,默认从0开始递增

带有显式值的枚举

你也可以为枚举成员指定整数值(包括负数或十六进制数)。

enum Days
{
Sunday = 1,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday = 0 // 可以显式地将一个枚举成员的值设置为0
}
// 或者直接使用十六进制
enum Colors : ushort
{
Red = 0x0001,
Green = 0x0002,
Blue = 0x0004
}

注意:

  • 如果在枚举的某个成员上指定了值,则下一个成员的值将自动设置为前一个成员的值加1,除非显式指定了另一个值。
  • 在上面的Colors枚举中,: ushort指定了枚举的底层类型为ushort。默认情况下,枚举的底层类型是int你也可以将其指定为bytesbyteshortushortintuintlongulong

使用枚举

枚举的使用非常简单,就像使用其他整型变量一样。

Days today = Days.Monday;
Console.WriteLine((int)today); // 输出:2
Colors myColor = Colors.Red;
Console.WriteLine((ushort)myColor); // 输出:1

注意,当需要将枚举值转换为整数时,需要显式地进行类型转换(如上例所示)。

枚举的遍历

由于枚举本质上是一个整数值的集合,所以不能直接遍历。但是,你可以通过Enum.GetNamesEnum.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中的接口

在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接口,我们就可以用相同的方式来处理它们的移动逻辑,而不需要关心它们内部的具体实现细节。

接口的优势

  1. 解耦:接口使得类的实现与使用解耦,即类的使用者不需要知道类的具体实现细节,只需要知道类实现了哪些接口。
  2. 灵活性:接口允许在不影响现有代码的情况下添加新的实现类,提高了系统的可扩展性。
  3. 易于测试:接口使得模拟(Mocking)变得容易,可以轻松地创建接口的模拟对象来进行单元测试,而不需要依赖实际的实现类。

在Unity游戏中,接口的应用远不止于此,它们可以用于实现各种游戏逻辑和功能,帮助开发者构建更加灵活和可维护的游戏系统。

Unity中的API

API(Application Programming Interface,应用程序编程接口)

并不仅仅是指类,API更广泛地定义为一组协议、规范或工具,它们为软件应用程序(包括Web服务、操作系统、数据库系统等)之间的交互提供了明确的方法和约定。

API可以包含多种元素,包括但不限于:

  1. 函数:在面向对象编程中,这通常表现为类的方法或静态函数。但在其他编程范式中,API也可以仅仅是一组可以调用的函数。

  2. :在面向对象的语言中,类本身就可以作为API的一部分,因为它们封装了数据和方法,提供了与对象交互的接口。

  3. 数据类型:API还可以定义特定的数据类型,这些数据类型用于在API的调用中传递和接收数据。

  4. 协议:在网络编程中,API可能定义了一种或多种通信协议,这些协议规定了客户端和服务器之间如何交换数据。

  5. 规范:API规范文档详细说明了如何使用API,包括它提供的函数、类、数据类型、协议以及任何必要的调用参数、返回值和错误处理机制。

  6. :有时,API会以库的形式提供,这些库包含了实现API所需的所有类和函数,开发者可以通过包含这些库来在自己的应用程序中使用API。

  7. Web服务:在现代Web开发中,API经常以Web服务的形式出现,这些服务通过HTTP请求和响应来提供数据和功能。

在unity中的应用

  1. 游戏对象(GameObject)和组件(Component)
    • GameObject是Unity中的基本构建块,代表场景中的任何实体。
    • Component是附加到GameObject上的对象,负责实现具体的功能,如物理模拟(Rigidbody)、碰撞检测(Collider)、渲染(Renderer)等。
    • Unity API提供了创建、修改和销毁GameObject及其组件的方法。
  2. 时间和输入
    • Time类提供了一系列与游戏时间相关的函数,如Time.time(表示从游戏开始到现在的时间)、Time.deltaTime(表示上一帧到当前帧的时间间隔)等。
    • Input类则用于处理玩家输入,如键盘、鼠标和游戏手柄的输入。
  3. 数学和物理
    • Unity API包含了丰富的数学函数,如Mathf类中的Abs(绝对值)、Pow(幂运算)等,以及Vector3Quaternion等类,用于处理向量和四元数运算。
    • 物理引擎相关的API允许开发者模拟真实的物理效果,如重力、碰撞、摩擦力等。
  4. 渲染和相机
    • 渲染相关的API用于控制游戏画面的渲染效果,如光照、阴影、材质等。
    • Camera组件和相关的API用于定义玩家的观察视角和渲染范围。
  5. 事件和生命周期
    • Unity API提供了一系列事件函数,如StartUpdateFixedUpdateLateUpdate等,它们在游戏的生命周期中按特定顺序被调用,允许开发者在这些时间点执行特定的代码。
    • 还有一些特定的生命周期函数,如AwakeOnEnableOnDisableOnDestroy等,它们在GameObject或组件的生命周期中被调用。
  6. 调试和日志
    • Unity API还提供了调试和日志记录的功能,如Debug.LogDebug.LogWarningDebug.LogError等,帮助开发者在开发过程中跟踪和解决问题。
  7. 网络和多线程
    • 对于需要网络通信或多线程处理的游戏,Unity API也提供了相应的支持。

总的来说,Unity中的API是开发者在游戏开发过程中不可或缺的工具,它们为开发者提供了丰富的功能和灵活的接口,使得游戏开发变得更加高效和便捷。通过熟练掌握和使用这些API,开发者可以创建出更加复杂和精彩的游戏作品。

判断GameObject.Find是否找到了

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的代码  
        }  
    }  
}

unity代码没有补全提示

  1. 检查Unity编辑器设置
    • 确保Unity编辑器的“Preferences” -> “Editor” -> “Code Editor”设置正确。如果你使用的是Visual Studio作为代码编辑器,确保它已经正确设置为默认编辑器。
    • 在“Preferences” -> “External Tools”中检查外部工具的路径是否设置正确,特别是如果你使用了Visual Studio或Visual Studio Code等IDE。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值