IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> C#初级编程 -> 正文阅读

[游戏开发]C#初级编程

一、Awake 和 Start

Awake 和 Start 是在加载脚本时自动调用的两个函数,在一个对象绑定脚本的生命周期内只能调用一次。

Awake:还未启用脚本组件便已调用,适合用于在脚本与初始化之间设置任何引用
Start:在Awake之后调用,直接在首次更新之前调用,前提是已经启用了脚本组件,这样可以将初始化代码的任何部分,延迟到真正需要的时候再调用。

例如,有一个敌人进入游戏,并使用Awake获得了分配的弹药,但要想射击,需在启用脚本组件时,使用Start在定义时间实现射击。

using UnityEngine;
using System.Collections;

public class AwakeAndStart : MonoBehaviour
{
    void Awake ()
    {
        Debug.Log("Awake called.");
    }
    
    void Start ()
    {
        Debug.Log("Start called.");
    }
}

二、Update 和 FixedUpdate

Update:在每个使用它的脚本中每帧调用一次,基本上只要需要变化或调整都需要使用Update来实现。Update并不是按固定时间调用,如果某一帧比下一帧处理时间长,那么调用的时间间隔就会不同。
FixedUpdate:与Update类似,但FixedUpdate按固定时间调用,调用后会立即进行任何必要的物理计算,因此任何影响刚体(物理对象)的动作都应使用FixedUpdate执行。

using UnityEngine;
using System.Collections;

public class UpdateAndFixedUpdate : MonoBehaviour
{
    void FixedUpdate ()
    {
        Debug.Log("FixedUpdate time :" + Time.deltaTime);
    }
    
    
    void Update ()
    {
        Debug.Log("Update time :" + Time.deltaTime);
    }
}

输出
Unity中的Update和其他许多特殊函数,都可以在Visual Studio中迅速轻松创建,使用MonoBehaviour脚本编写向导即可实现。按Ctrl+Shift+M启动向导,勾选想要添加的方法即可在光标处添加函数。

三、启用和禁用组件

只需使用enabled标记,设为false即可禁用组件。
注意,脚本也是组件,也可以通过enabled禁用。

using UnityEngine;
using System.Collections;

public class EnableComponents : MonoBehaviour
{
    private Light myLight;
    
    
    void Start ()
    {
        myLight = GetComponent<Light>();
    }
    
    
    void Update ()
    {
        if(Input.GetKeyUp(KeyCode.Space))//按下空格
        {
            myLight.enabled = !myLight.enabled;
        }
    }
}

四、SetActive、Active Self、Active in Hierarchy

SetActive:通过脚本在场景中激活或停用对象。需要注意的是,停用父对象,那么场景中活跃的子对象也会停止,但子对象仍在其层次结构中保持活跃状态。下图例子中,停用父对象PhysicsDoor,子对象Door变灰,但在层次结构中仍旧保持活跃状态。
停用父对象
子对象仍旧活跃

SetActive示例——停用对象
------------------------------------------------------
using UnityEngine;
using System.Collections;

public class ActiveObjects : MonoBehaviour
{
    void Start ()
    {
        gameObject.SetActive(false);
    }
}
------------------------------------------------------

Active Self:检测对象在场景中是否处于活跃状态。
Active in Hierarchy:检测对象在层次结构中是否处于活跃状态。

Active Self、Active in Hierarchy示例——输出对象状态
-----------------------------------------------------------------------
using UnityEngine;
using System.Collections;

public class CheckState : MonoBehaviour
{
    public GameObject myObject;
    
    
    void Start ()
    {
        Debug.Log("Active Self: " + myObject.activeSelf);
        Debug.Log("Active in Hierarchy" + myObject.activeInHierarchy);
    }
}
-----------------------------------------------------------------------

五、位置和旋转

1. 位置变换:transform.Translate()

-----------------------------------------------------------------------
参数:Vector3
Time.deltaTime:两次Update函数调用的间隔时长
功能:每帧移动一定距离,乘上Time.deltaTime后为匀速运动
transform.Translate(Vector3.forward * moveSpeed * Time.deltaTime);
-----------------------------------------------------------------------

2. 旋转:transform.Rotate()

-----------------------------------------------------------------------
参数1:Vector3,表示围绕哪个轴旋转
参数2float,表示旋转量
transform.Rotate(Vector3.up, turnSpeed * Time.deltaTime);
-----------------------------------------------------------------------

3. 应用
在小飞机上挂载脚本,实现方向键控制小飞机的运动速度和方向。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MyJet : MonoBehaviour
{
    public float moveSpeed = 0f;
    public float turnSpeed = 0f;
    // Start is called before the first frame update
    void Start()
    {    

    }
    // Update is called once per frame
    void Update()
    {
        if (Input.GetKey(KeyCode.UpArrow))
        {
            moveSpeed += 0.01f;
        }
        else if (Input.GetKey(KeyCode.DownArrow))
        {
            moveSpeed -= 0.01f;
        }
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            turnSpeed += 0.1f;
        }
        else if (Input.GetKey(KeyCode.RightArrow))
        {
            turnSpeed -= 0.1f;
        }
        if (Input.GetKey(KeyCode.Space))
        {
            moveSpeed = 0;
            turnSpeed = 0;
        }
        if (moveSpeed > 0)
        {
            transform.Rotate(Vector3.forward, turnSpeed * Time.deltaTime);
        }
        else if(moveSpeed < 0)
        {
            transform.Rotate(Vector3.forward, -turnSpeed * Time.deltaTime);
        }
        transform.Translate(Vector3.up * Time.deltaTime * moveSpeed);
    }
}

六、transform.lookAt(Transform target)

LookAt 函数使一个游戏对象的变换组件面向另一个游戏对象的变换组件,也就是使自身的Z轴指向另一个游戏对象,可用于摄像机对运动物体的跟踪拍摄。

using UnityEngine;
using System.Collections;

public class CameraLookAt : MonoBehaviour
{
    public Transform target;
    
    void Update ()
    {
        transform.LookAt(target);
    }
}

七、线性插值

在制作游戏时,有时可以在两个值之间进行线性插值。这是通过 Lerp 函数来完成的。线性插值会在两个给定值之间找到某个百分比的值。例如,我们可以在数字 3 和 5 之间按 50% 进行线性插值以得到数字 4。这是因为 4 是 3 和 5 之间距离的 50%。
在 Unity 中,有多个 Lerp 函数可用于不同类型。对于我们刚才使用的示例,与之等效的将是 Mathf.Lerp 函数,如下所示:

// 在此示例中,result = 4
float result = Mathf.Lerp (3f, 5f, 0.5f);

Mathf.Lerp 函数接受 3 个 float 参数:一个 float 参数表示要进行插值的起始值,另一个 float 参数表示要进行插值的结束值,最后一个 float 参数表示要进行插值的距离。在此示例中,插值为 0.5,表示 50%。如果为 0,则函数将返回“from”值;如果为 1,则函数将返回“to”值。
Lerp 函数的其他示例包括 Color.Lerp 和 Vector3.Lerp。这些函数的工作方式与 Mathf.Lerp 完全相同,但是“from”和“to”值分别为 Color 和 Vector3 类型。在每个示例中,第三个参数仍然是一个 float 参数,表示要插值的大小。这些函数的结果是找到一种颜色(两种给定颜色的某种混合)以及一个矢量(占两个给定矢量之间的百分比)。
让我们看看另一个示例:

Vector3 from = new Vector3 (1f, 2f, 3f);
Vector3 to = new Vector3 (5f, 6f, 7f);

// 此处 result = (4, 5, 6)
Vector3 result = Vector3.Lerp (from, to, 0.75f);

在此示例中,结果为 (4, 5, 6),因为 4 位于 1 到 5 之间的 75% 处,5 位于 2 到 6 之间的 75% 处,而 6 位于 3 到 7 之间的 75% 处。
使用 Color.Lerp 时适用同样的原理。在 Color 结构中,颜色由代表红色、蓝色、绿色和 Alpha 的 4 个 float 参数表示。使用 Lerp 时,与 Mathf.Lerp 和 Vector3.Lerp 一样,这些 float 数值将进行插值。
在某些情况下,可使用 Lerp 函数使值随时间平滑。请考虑以下代码段:

void Update ()
{
    light.intensity = Mathf.Lerp(light.intensity, 8f, 0.5f);
}

如果光的强度从 0 开始,则在第一次更新后,其值将设置为 4。下一帧会将其设置为 6,然后设置为 7,再然后设置为 7.5,依此类推。因此,经过几帧后,光强度将趋向于 8,但随着接近目标,其变化速率将减慢。请注意,这是在若干个帧的过程中发生的。如果我们不希望与帧率有关,则可以使用以下代码:

void Update ()
{
    light.intensity = Mathf.Lerp(light.intensity, 8f, 0.5f * Time.deltaTime);
}

这意味着强度变化将按每秒而不是每帧发生。
请注意,在对值进行平滑时,通常情况下最好使用 SmoothDamp 函数。仅当您确定想要的效果时,才应使用 Lerp 进行平滑。

八、Destroy

在运行时使用 Destroy() 函数删除游戏对象和组件。

//按下空格后,脚本挂载的游戏对象被删除。
using UnityEngine;
using System.Collections;

public class DestroyBasic : MonoBehaviour
{
    void Update ()
    {
        if(Input.GetKey(KeyCode.Space))
        {
            Destroy(gameObject);
        }
    }
}
//按下空格后,指定的游戏对象被删除。
using UnityEngine;
using System.Collections;

public class DestroyOther : MonoBehaviour
{
    public GameObject other;
    
    
    void Update ()
    {
        if(Input.GetKey(KeyCode.Space))
        {
            Destroy(other);
        }
    }
}
//删除组件
using UnityEngine;
using System.Collections;

public class DestroyComponent : MonoBehaviour
{
    void Update ()
    {
        if(Input.GetKey(KeyCode.Space))
        {
            Destroy(GetComponent<MeshRenderer>());
        }
    }
}

九、GetButton 和 GetKey

GetButton 和 GetKey 用于在 Unity 项目中获取输入的按钮或键。
GetKey:使用KeyCode明确指定按键名称。
GetButton:指定自定义的控制。
输入管理器可以指定输入名称并给它指定一个键或按钮。方法为:顶部菜单 Edit -> Project Settings -> Input Manager,通过设置 Name 和 Positive Button 引用该按键。
输入共有三种状态并返回相应布尔值。

1. 还未按下按键
在这里插入图片描述
2. 按下按键后的第一帧
在这里插入图片描述
3. 保持按住按键
在这里插入图片描述
4. 松开按键后的第一帧
在这里插入图片描述
5. 停止动作
在这里插入图片描述
总之,Up 和 Down 仅在按下和松开的第一帧变为 true,其余时候为 false,而 GetButton 可以用来判断是否按住了按键,GetKey也是如此。

十、GetAxis

GetAxis 是基于轴输入,与 GetButton、GetKey 类似,同样可以通过 Input Manager 设置,但返回的是介于-1到1之间的浮点数,相当于是介于正负1之间的滑尺。
Positive Button:按下后返回值介于0到1之间。
Negative Button:按下后返回值介于-1到0之间。
Gravity:设置输入重新居中的速度。仅当 Type 设置为 key / mouse button 时,此属性才适用。Gravity 越高,归零的速度越快,反之越慢。
Sensitivity:影响按钮按下后到达1或-1的速度,对于键盘输入,值越大,响应越快。较小的值将更加平滑。对于鼠标增量,该值会缩放实际鼠标增量。
Dead:任何小于此数字的正值或负值都视为零。适用于游戏杆。
Snap:启用此选项可在接收相反输入后立即将轴值重置为零。仅当 Type 设置为 key / mouse button 时,此属性才适用。

void Update () 
    {
        float h = Input.GetAxis("Horizontal");
        float xPos = h * range;
       
        transform.position = new Vector3(xPos, 2f, 0);
    }
//Input.GetAxis("Raw"):仅放回整数,不返回非整数,适合需要精准控制的二维游戏。

十一、GetComponent

功能:访问其他脚本或组件。
用法:GetComponent<>( ),尖括号的作用是让类型作为参数

UsingOtherComponents

using UnityEngine;
using System.Collections;

public class UsingOtherComponents : MonoBehaviour
{   
    public GameObject otherGameObject;  
    //anotherScript和yetAnotherScript存放对其他脚本的引用,也就是以脚本名称为类型的变量
    private AnotherScript anotherScript;
    private YetAnotherScript yetAnotherScript;
    private BoxCollider boxCol;
    
    
    void Awake ()
    {
    	//AnotherScript和UsingOtherComponents挂载在同一个游戏对象上,所以可以直接使用GetComponent
        anotherScript = GetComponent<AnotherScript>();
        //yetAnotherScript挂载在另一游戏对象上,所以要用otherGameObject调用
        yetAnotherScript = otherGameObject.GetComponent<YetAnotherScript>();
        //也可用于访问API未公开的其他组件
        boxCol = otherGameObject.GetComponent<BoxCollider>();
    }
    
    
    void Start ()
    {
        boxCol.size = new Vector3(3,3,3);
        Debug.Log("The player's score is " + anotherScript.playerScore);
        Debug.Log("The player has died " + yetAnotherScript.numberOfPlayerDeaths + " times");
    }
}

AnotherScript

using UnityEngine;
using System.Collections;

public class AnotherScript : MonoBehaviour
{
    public int playerScore = 9001;
}

YetAnotherScript

using UnityEngine;
using System.Collections;

public class YetAnotherScript : MonoBehaviour
{
    public int numberOfPlayerDeaths = 3;
}

十二、数据类型

Value(值类型)Reference(引用类型)
intClasses
floatTransform
doubleGameobject
bool
char
Structs(Vector3,Quaternion)
  • 值类型变量:包含某个值(改变后不改变原来的值)
  • 引用类型变量:包含值存储位置的存储地址(改变后该位置存储的值改变)

DatatypeScript

using UnityEngine;
using System.Collections;

public class DatatypeScript : MonoBehaviour 
{
    void Start () 
    {
        //值类型变量————游戏对象未发生移动
        Vector3 pos = transform.position;
        pos = new Vector3(0, 2, 0);
        
        //引用类型变量————游戏对象移动
        Transform tran = transform;
        tran.position = new Vector3(0, 2, 0);
    }
}

十三、Instantiate

在运行期间使用 Instantiate 创建预制件的克隆体

Instantiate(projectile,barrelEnd.position,barrelEnd.rotation)
-------------------------------------------------------------
projectile:要实例化的对象
barrelEnd.position:新克隆的对象的位置
barrelEnd.rotation:新克隆的对象的旋转
Instantiate(projectile):克隆体默认出现在挂载脚本的对象的位置
-------------------------------------------------------------

UsingInstantiate

using UnityEngine;
using System.Collections;

public class UsingInstantiate : MonoBehaviour
{
    public Rigidbody rocketPrefab;
    //barrelEnd是公有变量,可以创建空对象后拖入Unity属性框中,用作定位
    public Transform barrelEnd;
    
    
    void Update ()
    {
        if(Input.GetButtonDown("Fire1"))
        {
            Rigidbody rocketInstance;
            //Instantiate一般返回object类型,这里需要添加作用力
            //因此用 as Rigidbody强制类型转换
            rocketInstance = Instantiate(rocketPrefab, barrelEnd.position, barrelEnd.rotation) as Rigidbody;
            rocketInstance.AddForce(barrelEnd.forward * 5000);
        }
    }
}

RocketDestruction

using UnityEngine;
using System.Collections;

public class RocketDestruction : MonoBehaviour
{
    void Start()
    {
        Destroy (gameObject, 1.5f);//经过指定秒数后移除对象
    }
}

十四、数组

使用数组将变量集合在一起以便于管理

Arrays

using UnityEngine;
using System.Collections;

public class Arrays : MonoBehaviour
{
    public GameObject[] players;

    void Start ()
    {
        //FindGameObjectsWithTag:返回场景中带有指定标记的游戏对象组成的数组
        players = GameObject.FindGameObjectsWithTag("Player");
        
        for(int i = 0; i < players.Length; i++)
        {
            Debug.Log("Player Number "+i+" is named "+players[i].name);
        }
    }
}

十五、Invoke

Invoke 函数可用于安排在以后的时间进行方法调用。

Invoke(name,time)
-------------------------------------------------------
name:字符串类型,想调用的方法名称
time:以秒为单位的延时时长
只有不包含参数,且返回类型为void的函数能调用Invoke
-------------------------------------------------------

InvokeScript

using UnityEngine;
using System.Collections;

public class InvokeScript : MonoBehaviour 
{
    public GameObject target;
    
    
    void Start()
    {
        Invoke ("SpawnObject", 2);
    }
    
    void SpawnObject()
    {
        Instantiate(target, new Vector3(0, 2, 0), Quaternion.identity);
    }
}
InvokeRepeating(name,timeBeforeMethod,timeAfterMethod)
-------------------------------------------------------
name:字符串类型,想调用的方法名称
timeBeforeMethod:调用方法之前的延时,以秒为单位
timeAfterMethod:后续方法调用间隔的延时,以秒为单位
-------------------------------------------------------

CancelInvoke(name)
-------------------------------------------------------
无参:停止这个脚本中由Invoke调用的所有实例
name:想暂停的方法名称,停止某个指定的Invoke
-------------------------------------------------------

InvokeRepeating

using UnityEngine;
using System.Collections;

public class InvokeRepeating : MonoBehaviour 
{
    public GameObject target;
    
    
    void Start()
    {
        InvokeRepeating("SpawnObject", 2, 1);
    }
    
    void SpawnObject()
    {
    	//x轴和z轴位置随机
        float x = Random.Range(-2.0f, 2.0f);
        float z = Random.Range(-2.0f, 2.0f);
        Instantiate(target, new Vector3(x, 2, z), Quaternion.identity);
    }
}

十六、枚举

枚举可用于创建相关常量的集合。

格式:enum Name {A, B, C, D};
每个常量都有默认值,为从0开始往上数的整数,上例A=0,B=1,C=2,D=3
enum Name {A=1, B, C, D};默认值从1开始往上数
也可以声明每个常量的值
枚举中常量的类型可以更改为任意整数类型 ->enum Name : short {A, B, C, D};

EnumScript

using UnityEngine;
using System.Collections;

public class EnumScript : MonoBehaviour 
{
    enum Direction {North, East, South, West};

    void Start () 
    {
        Direction myDirection;
        
        myDirection = Direction.North;
    }
    
    Direction ReverseDirection (Direction dir)
    {
        if(dir == Direction.North)
            dir = Direction.South;
        else if(dir == Direction.South)
            dir = Direction.North;
        else if(dir == Direction.East)
            dir = Direction.West;
        else if(dir == Direction.West)
            dir = Direction.East;
        
        return dir;     
    }
}

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-08-17 15:43:53  更:2021-08-17 15:44:30 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/20 17:42:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码