Unity的学习(三):古迹探险

一、新建项目

新建项目,并在Assets下右键Import Package ->Custom Package导入资源。如下图所示。
在这里插入图片描述
在这里插入图片描述

二、地形设计

地形工具的使用可以参考Unity官方文档

2.1创建地形

在Hierarchy中右键创建Terrain(地形),同时在Assets中会出现New Terrain(保存的是地形相关数据),将其重命名为Terrain Data并将其放入创建的Terrain文件夹中。
在这里插入图片描述

2.2 调整地形的长度和宽度

在Hierarchy视图中选中Terrain,可以在Inspector视图中看到Terrain游戏物体的组件Terrain,这时点击齿轮(Terrain Settings),在其中可以设置许多地形相关属性。找到Terrain Width 和Terrain Length以及Terrain Height(地形的最大高度),将他们的值设为50,每一个在修改后,按下回车将会生效。如下图所示。
在这里插入图片描述

2.3 Raise or Lower Terrain(升高或降低地形)

在这里插入图片描述

其中
Brush size:用来调整刷子尺寸的
Opacity:地形强度,当Opacity越大时,地形升高的越快。

按住shift键并且用刷子刷地形可以降低地形。
在这里插入图片描述

详细的可以参考Unity官方文档

2.4 Smooth Height

此工具可以将地形设计的更加平滑。

2.5 Paint Texture

使用 Paint Texture 工具可将纹理(如草、雪或沙)添加到地形。如下图所示。在这里插入图片描述

详情请参考Unity官方文档的Paint Texture地形图层

2.6 Paint Trees

通过点击Paint Trees图标可以在地形上摆放一些树,如下图所示。
在这里插入图片描述

详细请参考Unity官方文档

2.7 Paint Details

通过点击Paint Details图标,可以对草和其他一些细节进行处理,如下图所示。
在这里插入图片描述
详细的请参考Unity官方文档

三、古迹探险地形设计

此处自由发挥,就不描述了。
由于太亮,所以需要**调节光的强度。**如下图所示。
在这里插入图片描述

最终效果类似于如下图。
在这里插入图片描述

四、相机和当前视野保持一致

让相机和当前视野保持一致。选择Main Camera -> GameObject -> Align With View。如下图所示。
在这里插入图片描述

五、刚体

在场景中创建球体,运行游戏发现球体在半空中并没有掉落,这时就需要给球体游戏对象添加Rigidbody(刚体)组件来实现物理效果。
在这里插入图片描述
在这里插入图片描述
Mass:对象的质量(默认为千克)
Drag:阻力
Angular Drag:旋转时的阻力
Use Gravity:是否受重力影响
Freeze Position:锁定刚体沿世界 X、Y 和 Z 轴的移动。
Freeze Rotation:锁定刚体围绕局部 X、Y 和 Z 轴旋转。

有关刚体的更多信息,请参考Unity官方文档

六、碰撞器

碰撞器组件定义对象的形状以便用于物理碰撞。如下图所示,当禁用球体的碰撞器(Sphere Collider)后,球体会直接穿过地面,而没禁用碰撞器时,则会与地面发送物理碰撞效果,也就不会穿过地面。

注意:碰撞发生的条件,两个物体必须都有碰撞体(Collider),并且其中一个需要有刚体(Rigidbody)。
在这里插入图片描述
关于碰撞器的详细信息可以查看Unity官方文档

6.1 碰撞检测的方法

在Assets下创建Scripts文件夹,在Scripts中创建命名为Sphere的C#脚本,并将脚本挂载到Sphere游戏物体上。如下图所示。
在这里插入图片描述

可以使用以下方法(详情可以参考Unity官方文档)来进行碰撞检测,这些方法都是由Unity调用的:

    //当该碰撞体/刚体已开始接触另一个刚体/碰撞体时,调用 OnCollisionEnter。(碰撞发生时调用)
    private void OnCollisionEnter(Collision collision) {
        
    }

    //当该碰撞体/刚体已停止接触另一个刚体/碰撞体时,调用 OnCollisionExit。(碰撞结束时调用)
    private void OnCollisionExit(Collision collision) {
        
    }

    //对应正在接触刚体/碰撞体的每一个碰撞体/刚体,每帧调用一次 :ref::OnCollisionStay。(碰撞过程中调用)
    private void OnCollisionStay(Collision collision) {
        
    }

6.2 碰撞信息的获取

//当该碰撞体/刚体已开始接触另一个刚体/碰撞体时,调用 OnCollisionEnter。(碰撞发生时调用)
    private void OnCollisionEnter(Collision collision) {
        //获取我们和哪一个碰撞器发生了碰撞
        print(collision.collider); 
        //获取我们碰撞的游戏物体的名字
        print(collision.collider.name);
        //获取我们碰撞的游戏物体的标签
        print(collision.collider.tag);
    }

在这里插入图片描述

6.3 触发检测

有时候我们需要做一些机关,当角色靠近机关时会触发一些效果,这时我们就可以将碰撞器设置为触发器(勾选 Is Trigger)。如下图所示。可以创建一个Cube,移除掉Mesh Filter和Mesh Renderer组件。
在这里插入图片描述

或者直接创建一个空游戏物体(Create Empty),然后给它添加碰撞器(Collider),并将碰撞器的Is Trigger勾选。并可以使用Edit Collider图标对Collider范围进行调节。如下图所示。
在这里插入图片描述

6.4 触发检测的方法

可以使用以下方法来进行触发检测,详情参考Unity官方文档

	//当一个游戏物体开始进入到另一个游戏物体触发区域时,调用OnTriggerEnter
    private void OnTriggerEnter(Collider other) {
        
    }

    //当一个游戏物体离开另一个游戏物体触发区域时,调用OnTriggerExit
    private void OnTriggerExit(Collider other) {
        
    }

    //当一个游戏物体正在另一个游戏物体触发区域时,调用OnTriggerStay
    private void OnTriggerStay(Collider other) {
        
    }

6.5 触发信息的获取

//当一个游戏物体开始进入到另一个游戏物体触发区域时,调用OnTriggerEnter
    private void OnTriggerEnter(Collider other) {
        //获取触发器
        print(other);
        //获取触发器所在游戏物体的名字
        print(other.name);
        //获取触发器所在游戏物体的标签
        print(other.tag);
    }

在这里插入图片描述

七、Unity中四种灯光

关于光源的详细信息可以参考Unity官方文档

7.1 Directional Light

方向光对于在场景中创建诸如阳光的效果非常有用。方向光在许多方面的表现很像太阳光,可视为存在于无限远处的光源。方向光没有任何可识别的光源位置,因此光源对象可以放置在场景中的任何位置。
在这里插入图片描述

7.2 Point Light

点光源位于空间中的一个点,并在所有方向上均匀发光。照射到表面的光线的方向是从接触点返回到光源对象中心的线。强度随着远离光源而衰减,在到达指定距离时变为零。点光源可用于模拟场景中的灯和其他局部光源。还可以用点光源逼真地模拟火花或爆炸照亮周围环境。
在这里插入图片描述

7.3 Spot Light

像点光源一样,聚光灯具有指定的位置和光线衰减范围。不同的是聚光灯有一个角度约束,形成锥形的光照区域。锥体的中心指向光源对象的发光 (Z) 方向。聚光灯锥体边缘的光线也会减弱。加宽该角度会增加锥体的宽度,并随之增加这种淡化的大小,称为“半影”。
聚光灯通常用于人造光源,例如手电筒、汽车前照灯和探照灯。
在这里插入图片描述

7.4 Area Light

面光源是通过空间中的矩形来定义的。光线在表面区域上均匀地向所有方向上发射,但仅从矩形的所在的面发射。无法手动控制面光源的范围,但是当远离光源时,强度将按照距离的平方呈反比衰减。由于光照计算对处理器性能消耗较大,因此面光源不可实时处理,只能烘焙到光照贴图中。
在这里插入图片描述

八、给场景添加火堆

8.1 给场景添加光源

给场景添加光源,并对光的颜色做一些设置。
在这里插入图片描述

8.2 添加火堆

在这里插入图片描述

给火堆添加光源,并将其设为Prefab(预制体)。
在这里插入图片描述

九、Lightmapping

当我们在场景中不使用光照贴图的话,光对场景的影响是需要实时计算的,这样比较耗费性能。如果视野Lightmapping的话,会提前将光照信息计算好,然后烘焙成一个贴图,并将贴图贴到模型上,这样在实际运行中就不需要进行重复计算了。
在这里插入图片描述
在这里插入图片描述

由于火光会有动画效果,一闪一闪的,如果用Backed的话,效果是不变的。所以火堆这里需要用Mixed。
在这里插入图片描述

观察Scene视图,发现其中没有阴影。
在这里插入图片描述

十、使用粒子系统创建火焰

选择Bonfire预制体,创建粒子系统。
在这里插入图片描述
调整形状。
在这里插入图片描述

调整Start LifeTime和Start Speed
在这里插入图片描述

在这里插入图片描述
比较详细的过程可以去看siki学院的视频

最终效果,如下图所示。
在这里插入图片描述

十一、给灯光添加闪烁效果

创建动画
在这里插入图片描述
在这里插入图片描述

给灯光添加运动动画效果,让火苗左右摇摆。
在这里插入图片描述

整个动画效果,如下图所示。
在这里插入图片描述

十二、导航系统(寻路系统)

要使用导航系统需要进行导航网格的烘焙,在烘焙之前需要确定Environment的static是勾选上的(确保Navigation Static勾选上就行了)。
在这里插入图片描述

12.1 生成导航网格

在Navigation -> Bake ->Bake按钮。可通过Agent Radius来调节代理半径(类似于在障碍物的范围不可进行导航)。
在这里插入图片描述

对于草之类的,角色应该是可以通过的,我们需要将其Navigation Static勾选取消掉,然后再重新进行烘焙。
在这里插入图片描述

对于不能到达的,要选中物体->Navigation->Object->AI->Navigation Area->Not Walkable。
在这里插入图片描述
在这里插入图片描述

12.2 添加导航组件

想要控制角色在网格上行走,需要给角色添加导航组件Nav Mesh Agent,可通过Radius和Height调整宽度和高度。
在这里插入图片描述

12.3 通过导航组件控制角色的移动

通过鼠标点击地面,获取鼠标点击的点,将这个点设置为目的地,然后让角色到达目的地。

在Scripts文件夹下创建Hero脚本,并将其挂载到Hero游戏物体上。
在这里插入图片描述

12.3.1 射线检测

void Update() {

        //鼠标左键按下
        if (Input.GetMouseButtonDown(0)) {

            //射线检测
            //ScreenPointToRay:将屏幕座标转换为射线
            //Input.mousePosition:鼠标位置
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            //用于从射线投射获取信息的结构。
            RaycastHit hit;
            //Physics.Raycast():向场景中的所有碰撞体投射射线,并返回有关命中对象的详细信息,信息保存在hit中。
            if (Physics.Raycast(ray, out hit)) {
                print(hit.point);
            }


        }

    }

在这里插入图片描述

12.3.2 控制角色到达目的地

在Hero脚本中定义属性public NavMeshAgent agent;并将组件Nav Mesh Agent拖入。如下图所示。
在这里插入图片描述
在判断代码中用agent调用SetDestination()方法

 if (Physics.Raycast(ray, out hit)) {
       //print(hit.point);
       //设置目的地
       agent.SetDestination(hit.point);
}

效果,如下图所示。
在这里插入图片描述

完整代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class Hero : MonoBehaviour {

    public NavMeshAgent agent;

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

    }

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

        //鼠标左键按下
        if (Input.GetMouseButtonDown(0)) {

            //射线检测
            //ScreenPointToRay:将屏幕座标转换为射线
            //Input.mousePosition:鼠标位置
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            //用于从射线投射获取信息的结构。
            RaycastHit hit;
            //Physics.Raycast():向场景中的所有碰撞体投射射线,并返回有关命中对象的详细信息,信息保存在hit中。
            if (Physics.Raycast(ray, out hit)) {
                //print(hit.point);
                //设置目的地
                agent.SetDestination(hit.point);
            }


        }

    }
}

十三、控制摄像机的跟随

调节相机到合适的角度,创建FollowTarget脚本,并将其挂载到Main Camera游戏物体上。
在这里插入图片描述

在FollowTarget脚本中定义属性public Transform hero;保存,并在Unity中将Hero赋给hero。如下图所示。
在这里插入图片描述
代码:

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

public class FollowTarget : MonoBehaviour {

    //因为跟随目标,只需要目标的位置
    public Transform hero;

    //位置的偏移
    private Vector3 offset;

    // Start is called before the first frame update
    void Start() {
        //当前游戏物体位置减去角色hero的位置
        offset = transform.position - hero.position;
    }

    // Update is called once per frame
    void Update() {
        //相机跟随
        transform.position = offset + hero.position;
    }
}

效果:
在这里插入图片描述

十四、控制角色的动画播放

创建Animator Controller。
在这里插入图片描述

编辑状态机。
在这里插入图片描述
在脚本中设置参数的值进行动画的切换。
在这里插入图片描述
代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

public class Hero : MonoBehaviour {

    public NavMeshAgent agent;

    public Animator anim;

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

    }

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

        //鼠标左键按下
        if (Input.GetMouseButtonDown(0)) {

            //射线检测
            //ScreenPointToRay:将屏幕座标转换为射线
            //Input.mousePosition:鼠标位置
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);

            //用于从射线投射获取信息的结构。
            RaycastHit hit;
            //Physics.Raycast():向场景中的所有碰撞体投射射线,并返回有关命中对象的详细信息,信息保存在hit中。
            if (Physics.Raycast(ray, out hit)) {
                //print(hit.point);
                //设置目的地
                agent.SetDestination(hit.point);
            }


        }
        //agent.velocity.magnitude:速度的大小
        anim.SetFloat("speed",agent.velocity.magnitude);

    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章