Unity集训1

七月末开始集训Unity,数据结构和Shader。

第一天看了《Unity5实战》,感觉自己代码大多数都能看懂,却一直没有一整根线穿插起来。再一个,对于其中的一些细节,平时注意的不多,要把更多注意力放在上面,不可浅尝辄止。最后,很重要的一点是,在游戏制作过程中的设计思想,是非常重要的。

今天看了前三章,个人感觉第三章的东西比较多。第三章以FPS(第一人称设计类)游戏开发过程中各个部分的实现为主线。讲述了如下内容

1.射线射击,模拟开枪效果
也就是通过ScreenPointToRay(Vector3)方法,完成摄像机发送射线,完成开枪击中
2.准星和击中点添加可视化提示
准星的实现过程:
(1)锁定光标
(2)隐藏光标
(3)OnGUI的GUI.Label()实现在特定位置绘制准星
击中点的实现可以通过协成机制进行实现
(1)机制 (2)实现 (3)与异步的区别
3.被击中对象
4.敌人漫游(AI,超级简单的AI)
就是实现敌人的游荡,又不相互碰撞。即敌人物体本身发出射线,如果检测到碰撞的物体,就随机转动一个角度
5.跟踪角色状态
就是通过布尔值_alive判定是否敌人是否活着,活着的时候,才执行上述的漫游函数
6.通过生成预设体完成敌人的实例
创建预设体,每次通过Instantiate方法完成敌人的实例化,在实例化时注意,实例化之后的物体的物体都是object类型的,需要通过as Gameobject,完成类型的转换
7.通过预制体完成子弹的实例化
8.判定子弹与玩家伤害机制

主要问题有以下两个:
1.射线问题

Ray射线类和RaycastHit射线投射信息类是射线中常用的两个工具类。

用途:射线多用于碰撞检测(如:射击游戏里是否击中目标)、角色移动、判断是否触碰到3D世界中的哪些物体对象,进而操作等。

基础API:

Ray 射线类 :【使用鼠标拾取或者判断子弹是否碰到對象,需要往特定方向发射射线。方向可能是世界坐标中的一个矢量方向,或屏幕上某一点。针对后者,提供了两个API,如下:】

1、Ray Camera.main.ScreenPointToRay(Vector3 pos) 返回一条射线Ray从摄像机的近口點nearClip到屏幕指定一个点;若射线未碰撞到物体[需要含有碰撞器组件],碰撞点hit.point的值是(0,0,0);pos:利用实际像素值表示射线到屏幕上的位置。pos的x或者y分量由0增到最大值,射线將由一边移到另一边。但pos是在屏幕上,故z分量始终是0;

2、Ray Camera.main.ViewportPointToRay(Vector3 pos) 返回一条射线Ray从摄像机到视口(视口之外无效)指定一个点;pos:用單位化比例值的方式表示射线到屏幕上的位置。

RaycastHit 光线投射碰撞信息:

1、bool Physics.Raycast(Vector3 origin, Vector3 direction, float distance, int layerMask)

射线与碰撞器发生碰撞时返回真,否则未穿过任何碰撞器则返回false。【origin:在世界坐标中射线起点;direction:射线的方向矢量;distance:射线长度,即起点到设定的终点的距离,默认是无限长;layerMask:显示层掩码,指定层次的碰撞器碰撞,其他层次的碰撞則会被忽略掉。】

2、 bool Physics.Raycast(Ray ray, Vector3 direction, RaycastHit out hit, float distance, int layerMask)

在场景中投下可与所有碰撞器碰撞的一条光线,并返回碰撞的信息,包括位置等的信息。

3、 bool Physics.Raycast(Ray ray, float distance, int layerMask)

当光线投射与任何碰撞器交叉时为真,否则为假。

4、 bool Physics.Raycast(Vector3 origin, Vector3 direction, RaycastHit out hit,float distance, int layerMask)

当光线投射与任何碰撞器交叉时为真,否则为假。
注:如果从一个球型体的内部到外部用光线投射,返回为假。

distance: 射线的长度

hit: 使用c#中out关键字传入一个空的碰撞信息类,然后碰撞后赋值。可以得到碰撞物体的transform,rigidbody,point等信息。

layerMask: 只选定Layermask层内的碰撞器,其它层内碰撞器忽略。 选择性的碰撞

5、RaycastHit[] RaycastAll(Ray ray, float distance, int layerMask)

投射一条光线并返回所有碰撞,也就是投射光线并返回一个RaycastHit[]结构体。

6、layerMask:共有32個层,对应使用一个32位整数的个位來表示每个层级,这个位为1示使用该层,為0表示不使用该层。

以下是射线应用的部分

using UnityEngine;
using System.Collections;

public class RayTest : MonoBehaviour {
 
    void Start () {    
    }     
    void Update () 
    {
        if(Input.GetMouseButton(0))
        {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//从摄像机发出到点击坐标的射线
            RaycastHit hitInfo;
            if(Physics.Raycast(ray,out hitInfo))
            {
                Debug.DrawLine(ray.origin,hitInfo.point);//scene視圖可看到 DrawLine(Vector3 origin,Vector3 end,Color col):衹有儅發生碰撞時,在Scene視圖才可以看到畫出的射綫。
                GameObject Obj = hitInfo.collider.gameObject; Debug.Log("click object name is " + Obj.name); if(Obj.tag == "xx")//当射线碰撞目标为名字為xx的對象 ,执行以下操作  { DoSomething.... } } } } }

2.协程问题
一、开启协程:
我在Unity下创建了一个Cube(随便什么物体都行),然后把我的cs文件挂载上去。点击Unity上的开始按钮,运行:
代码如下:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class TestCoroutine : MonoBehaviour
{
    private GameObject cube;
    // Start is called before the first frame update
    void Start()
    {
        cube = GameObject.Find("Cube");
        Debug.Log(cube.transform.position);
        #region
        StartCoroutine(Test());
        #endregion
 
    }
 
    // Update is called once per frame
    void Update()
    {
        
    }
 
    private IEnumerator Test()
    {    
        Debug.Log(System.DateTime.Now+" hello");
        yield return new WaitForSeconds(3f);
        Debug.Log(System.DateTime.Now+" world");
    }
}

结果如下所示
在这里插入图片描述

也就是如下执行
1.首先我打印出了Cube的位置,这个没什么作用。就是想缓冲一下,让你看到程序进行到哪一步了。

2.然后开启了一个协程,这个协程函数是Test(),进入到Test()函数以后,首先打印出了当前系统时间+hello。

3.然后等待了3s,又打印出了当前系统时间+world。(我们也能算出来秒数增加了3s)

总结:yield return 相当于是“停止执行方法,并且下一帧从这里开始”。

二。协程与多线程的区别
上述是在网上找的例子。是一个协程的基本应用。但是协程跟多线程还不同。协程只是在执行时,跳转到另一个方法中,在经过一段时间之后,再次跳转回来
而多线程用在周雪薇同学的毕设中在使用过度画面的时候,贴一下代码

//在判定要跳转场景之后,loadLoadingLevel(目标场景)
MyLevelManager ml = new MyLevelManager();
            ml.LoadLoadingLevel("scence2");



public class MyLevelManager : MonoBehaviour
{

    static string nextLevel;
    AsyncOperation async;
    private float tempProgress;
    public Slider slider;
    public Text text;
    private bool show;

    void Start()
    {
        show = true;
        tempProgress = 0;
        if (SceneManager.GetActiveScene().name == "scenceguodu")
        {
            async = SceneManager.LoadSceneAsync(nextLevel);
            async.allowSceneActivation = false;
        }
    }
    public void LoadLoadingLevel(string nextLevelName)
    {
        nextLevel = nextLevelName;
        SceneManager.LoadScene("scenceguodu");

    }

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

        if (text && slider)
        {
            print("temp");
            tempProgress = Mathf.Lerp(tempProgress, async.progress, Time.deltaTime * 5);

            text.text = ((int)(tempProgress / 9 * 10 * 100)).ToString() + "%";
            slider.value = tempProgress / 9 * 10;
            if (tempProgress / 9 * 10 >= 0.995)
            {
                Debug.Log("Test");
                //tempProgress = 1;
                //tempProgress = Mathf.Lerp (tempProgress, async.progress, Time.deltaTime);

                text.text = 100.ToString() + "%";
                slider.value = 1;
                async.allowSceneActivation = true;
            }
        }
    }
}

其中SceneManager.LoadSceneAsync是异步加载场景,allowSceneActivation 一开始为false,设置为如果场景加载好了也不会自己跳场景。再后来,做了一个假的进度条,并没有计算加载。在之后执行了进度条之后,才把allowSceneActivation设置为true,完成跳转

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值