当前位置: 首页 > article >正文

Unity3D高级编程

1、标签(Tag)和图层(Layer)

他们都用于游戏物体分类,但是侧重点不一样。

标签便于代码中对特定物体进行操作。

图层则服务于渲染和碰撞管理,如控制摄像机渲染、光源影响及碰撞设置。

标签和图层的位置:

(1)标签Tag

用来对游戏物体进行分类的,从而更加方便的在代码中对某一类物体进行统一操作。

常用函数:

函数名        功能

GameObject.FindWithTag()

GameObject.FindGameObjectWithTag()

查找场景中指定标签的物体,但是当场景中有多个同样标签的物体时,无法保证返回的时哪一个。
GameObject.FindGameObjectsWithTag()返回场景中指定标签的所有物体

(2)层Layer

为了渲染和碰撞进行分类。

1)让摄像机只渲染某些层的物体,对另一些层的物体不渲染(即不显示)

2)让光源只照亮某些层的物体,而对另一些层的物体不影响。

3)供射线投射用于选择性地忽略碰撞体或创建碰撞

函数名功能
Physics.Raycast()发射射线、检测碰撞。其中有一个参数可以选择射线可以与哪些层的物体发生碰撞检测
collider2D.IsTouchingLayers()collider是一个2D碰撞体,此函数判断此2D碰撞体是否与指定层上的物体接触
gameObject.layer获取该游戏物体对应的层

4)设置层与层之间能否碰撞

在【Edit -> Project Settings -> Physics】中,

用来设置层与层之间能否发生碰撞的。如果把✔去掉,就表示行和列分别对应的两个层不会发生碰撞。

2、预制体

(1)预制体变体

当你将一个已经是预制体的游戏对象再次拖入Assets窗口时,弹窗就会提示,想要创建另一个原始预制体还是想要创建该原始预制体的变体。当选择第二个选项,则预制体变体创建成功。

预制体变体是原始预制体的派生类(是子类),子类也受到基类的影响,但也可以和基类有不同的地方。其不同的地方不受基类影响,子类也可以New实例,叫做预制体变体实例。

(2)修改预制体

如果Hierarchy中预制体实例被修改了,面板上就会多出一些选项。

当前预制体实例添加了2物体之后,图片出现"+"号,这表示这个2是新添加的,并不是原始预制体本身拥有的。此时可以:

1)Revert All:重置预制体,清除所有修改,把预制体变回原来的样子

2)Apply All:应用所有修改,报错所有修改,此时Assets中的预制体也将被改变

(3)将预制体实例变回一个普通的GameObject

断绝预制体实例和Assets中预制体的关系,它就会变回一个普通的游戏物体。

(4)删除预制体

当删除了Assets中的预制体,Hierarchy中的此预制体实例会变红,这时在提示我们预制体丢失,但不会影响使用,想让他不再是红色,破坏它把它变回普通游戏物体即可。

3、Time类使用

属性        功能
Time.time        游戏开始到现在所花的时间,单位是秒。
Time.timeScale时间缩放值,值1意味着实时。值0.5意味着半速,值0意味着暂停。用于游戏的快进暂停功能
Time.deltaTime上一帧到这一帧的游戏时间
Time.fixedDeltaTime固定时间间隔

4、异步加载场景

示例代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class AsyncTest : MonoBehaviour
{
    private AsyncOperation operation;
    float timer = 0;

    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine(loadScene());    
    }

    IEnumerator loadScene()
    {
        operation = SceneManager.LoadSceneAsync("SampleScene");
        operation.allowSceneActivation = false;
        yield return operation;

    }

    // Update is called once per frame
    void Update()
    {
        Debug.Log(operation.progress);
        timer += Time.deltaTime;

        if(timer > 5)
        {
            operation.allowSceneActivation = true;
        }
    }
}

5、角色移动

(1)直接修改组件位置

最基础的方式,是改变物体位置的最直接的方式。

适用于既没有物理系统,也对移动没有特殊要求的情况。

示例:

public class MoveTest : MonoBehaviour
{
    public float speed;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        Move();
    }

    void Move()
    {
        float moveX = Input.GetAxisRaw("Horizontal");
        float moveZ = Input.GetAxisRaw("Vertical");
        Vector3 dir = new Vector3(moveX, 0, moveZ).normalized;

        transform.Translate(dir * Time.deltaTime * speed);
    }
}

注意!!

1)GetAxis和GetAxisRaw的区别:如果你希望有一个平滑的输入响应,适用于移动角色等需要渐变效果的情况,可以使用 Input.GetAxis("Horizontal")。如果你需要快速、立即响应的输入,比如在一些快节奏的游戏中,可能更适合使用 Input.GetAxisRaw("Horizontal")。

2)直接移动的方法汇总:

  • transform.Translate(dir * Time.deltaTime * speed);
  • transform.position += dir * Time.deltaTime * speed;
  • transform.TransformPoint(dir * Time.deltaTime * speed);

(2)资源商城下载角色控制系统成品

比如去商城搜索 3rd person

(3)角色控制器组件Character Controller

向人物添加Character Controller组件

参数描述
Slope Limit 斜度限制可直接沿着向上移动的最大坡度
Step Offset 每步偏移量可直接跨越的最大障碍高度
Skin Width 蒙皮厚度皮肤厚度,值较大可减少抖动,较小可能导致角色卡住,一般设置为半径的10%(ps:但是这样会导致角色挨不着地面,所以这时候可以调整Center的Y轴值,即可使角色接触地面)
Min Move Distance 最小移动距离当橘色的单次移动距离小于该值时,则被忽略,不生效。可用于减少抖动
Radius & Height 半径和高度所控制角色的半径和高度

示例:

public class MoveTest : MonoBehaviour
{
    private CharacterController player;

    // Start is called before the first frame update
    void Start()
    {
        player = GetComponent<CharacterController>();
    }

    // Update is called once per frame
    void Update()
    {
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        Vector3 dir = new Vector3(horizontal, 0, vertical);
        player.SimpleMove(dir);

        if(player.isGrounded)
        {
            Debug.Log("正在地面上...");
        }
    }
}

注意!!移动的两个方法Move和SimpleMove的区别:

1)Move为更复杂的移动,不计算重力影响。

  • 无重力效果,自定实现重力,可做跳跃功能
  • 返回值(CollisionFlags对象),返回角色与物体碰撞的信息

2)SimpleMove:以一定速度来移动,移动时自动计算重力因素影响

  • 不受Y轴速度影响,自带重力吓偶句,无法实现跳跃功能
  • 返回值为Bool,当角色接触地面返回True,反之为False
  • SimpleMove方法是CharacterController组件提供的一个用于处理角色平面移动的简化方法,它自动处理了角色与地面的碰撞检测和摩擦,但它不支持跳跃等垂直方向的动作

(4)通过物理系统自己做

通过物理方式对物体施加力,改变物体运动状态的方式让物体移动,其中最核心的组件就是Rigidbody。

Rigidbody参数说明:

示例:

public class MoveTest : MonoBehaviour
{
    Rigidbody rb;
    public float speed;

    // Start is called before the first frame update
    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    // Update is called once per frame
    void Update()
    {
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        Vector3 dir = new Vector3(horizontal, 0, vertical).normalized;
        rb.MovePosition(transform.position + dir * Time.deltaTime * speed);
    }
}

刚体移动的方法:

  • AddForce: rb.AddForce(dir * speed * Time.deltaTime)
  • 修改velocity:rb.velocity += dir * speed * Time.deltaTime
  • MovePosition: rb.MovePosition(transform.position + dir * speed * Time.deltaTime);

(5)CharacterController和Rigidbody的区别

1)CharacterController

  • 处理斜坡
  • 处理台阶
  • 不会卡墙

2)Rigidbody

  • 自带重力
  • 提供阻力
  • 可以和物理对象交互

(6)完整的角色控制器代码

示例代码:

public class MoveTest : MonoBehaviour
{
    private CharacterController cc;
    public float speed = 12f;
    public float gravity = -9.81f;
    public float jumpHeight = 3f; // 跳跃高度

    public Transform groundCheck; // 用来获取生成球体的位置
    public float groundDistance = 0.4f;
    public LayerMask groundMask; // 值判断为地面的层

    Vector3 velocity;
    bool isGrounded; // 检测是否在地面

    // Start is called before the first frame update
    void Start()
    {
        cc = GetComponent<CharacterController>();
    }

    // Update is called once per frame
    void Update()
    {

        // CheckSphere 检验球,创建一个看不见的球用来检测,碰到就是true没有碰到就是false
        // 第一个值是球的位置,第二个是圆的半径,第三个是可筛选的层
        isGrounded = Physics.CheckSphere(groundCheck.position, groundDistance, groundMask); // 检测是否在地面

        if ((isGrounded && velocity.y < 0))
        {
            velocity.y = -2;
        }

        float moveX = Input.GetAxisRaw("Horizontal");
        float moveZ = Input.GetAxisRaw("Vertical");

        Vector3 dir = (transform.right * moveX + transform.forward * moveZ).normalized;

        // 平移
        cc.Move(dir * speed * Time.deltaTime);

        if(Input.GetButtonDown("Jump") && isGrounded)
        {
            // 物理公式 v=sqrt(v*-2*g)
            velocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity);
        }

        velocity.y += gravity * Time.deltaTime;

        // 再乘一个Time.deltaTime是由物理决定的1/2gt^2
        cc.Move(velocity * Time.deltaTime);

    }
}

6、拖尾(Trail Render组件)

新建拖尾(右键 -> 效果 -> 拖尾新增),也可以在其他物体上加Trail Render组件。

实现简单的拖尾修改配置如下:

效果:

7、游戏对象的Transform

Transform属性可以进行位置、旋转、大小的设置。

1)位置:position

2)旋转:rotate

3)大小:localScale

左右翻转怎么做?

position不行,rotate不行,所以可以考虑localScale属性。

localScale对应坐标的值*-1即可。

   x值从1变为-1后:   


http://www.kler.cn/a/394647.html

相关文章:

  • 《鸿蒙HarmonyOS应用开发从入门到精通(第2版)》学习笔记——HarmonyOS技术理念
  • 【已解决】图片png转ico格式
  • Python einops库介绍
  • 【信息系统项目管理师】第13章:项目资源管理-基础和过程 考点梳理
  • 如何删除Mac上的系统数据
  • Numpy指南:解锁Python多维数组与矩阵运算(下)
  • 离线语音识别自定义功能怎么用?
  • C#预处理器指令#if和#endif:掌握条件编译的艺术
  • 使用 Vision 插件让 GitHub Copilot 识图问答
  • windows C#-异常处理
  • 中断的硬件框架
  • 贪心算法day 06
  • Docker 中启动 NGINX 并配置 HTTPS 443 端口
  • 如何用Java爬虫“偷窥”淘宝商品类目API的返回值
  • Linux学习,ip 命令
  • 介绍一下位操作符(c基础)
  • python调用MySql详细步骤
  • 【干货】仓储管理SOP标准化操作!
  • torchvision库在进行图片转换操作中报antialias参数没有显式设置会导致不同图片后端中的值不统一的警告信息
  • Android Camera系列(六):MediaCodec视频编码上-编码YUV
  • Asp.NET Core Mvc中一个视图怎么设置多个强数据类型
  • PyQt入门指南五十二 版本控制与协作开发
  • Linux git-bash配置
  • 《深度学习》AlexNet网络
  • 11.14日志
  • vue中重置对象的好使方式(封装好的函数,可直接食用)