首页 > 其他分享 >基于Unity3d的google小恐龙游戏8-------背景音乐与第六个BOSS

基于Unity3d的google小恐龙游戏8-------背景音乐与第六个BOSS

时间:2024-03-17 14:58:23浏览次数:28  
标签:Unity3d 背景音乐 google gameObject Vector3 transform GameObject position public

前言

大家好,上一次unity练习记录中我添加了背景以及第五个boss,丰富了一下游戏内容,但是玩的时候发现好像有一些空洞,所以决定再次添加一些东西。本次练习主要是想要搞两个UI,以及背景音乐,然后再添加一个新的boss。其实我也很想再添加一些小怪,这些就是后话了。先把前面三个功能添加进去先!那么开始本次练习记录。

GUI--boss血条以及波次

之前也在书中学习了一些关于unity的GUI知识,但是最后发现好像现在unity已经不用传统的UI了,都改成了TMP了。所以在网上随便找了一些文章,查看了一下TMP的用法。

首先,TMP全称为TextMeshPro,是unity新推出的一种GUI对象,优点比其之前的UI多出了很多设置,同时清晰度也会自动匹配变化,不会出现方法之后变糊的情况。

使用TMP前需要像之前的UI一样,需要使用新的接口,在开头行输入-using TMPro;

这样才可以调用TMP的组件以及其各种功能。

获取TMP组件的方式一般是用-gameObject.GetComponent<TextMeshProUGUI>();

而gameObject则是对应TMP的实例。需要在代码中实例化。

而修改text就直接使用就可以了。

一般代码类似于:

using TMPro;

public TextMeshProUGUI bossLife;
public GameObject LifeCount;

LifeCount = GameObject.Find("bossLife");
rig = gameObject.GetComponent<Rigidbody>();//获取刚体对象
bossLife = LifeCount.GetComponent<TextMeshProUGUI>();
bossLife.text = "Wall : 100%";

 对于Boss的血量就可以直接使用这一种方式简单呈现,其实波次也是一样,大部分都可以直接使用以上格式修改ui内容,实现想要的效果。

然后对于boss血量的计算:因为我分为了两种boss,一种是会自己消失的,蠕虫,以及固定血量的。分别由三种计算方式:

自己消失的Boss血量计算:

string tem = "King Slime : " + ((int)(((liveTime - (Time.time - timeSummon)) / liveTime) * 100)).ToString() + "%";
bossLife.text = tem;

蠕虫boss的血量计算:

string tem = " ";
int num = 0;
for(int i = 1; i < 15; i++)
{
    if (nowWorm[i] != null)
    {
        num += 2;
    }
}
float numt = num / 30f;
tem = "Eater of Worlds : " + ((int)(numt * 100)).ToString() + "%";
bossLife.text = tem;

固定血量Boss计算:

string tem = "Wall : " + (int)((health / 80f)*100) + "%";
bossLife.text = tem;

这样就可以实现简单的Boss血量显示的功能了。文章最后有完整的内容显示视频:

 然后就是波次的代码:

波次代码和boss大同小异,定义好变量之后就可以了,以下为代码:

string tem = "WAVE : " + wave.ToString();
waveC.text = tem;

背景音乐 

背景音乐分为两种,一种是BOSS的音乐,一种是过场的音乐,这两种需要分开来播放。为了不让一个脚本过于复杂,我新创建了一个脚本---MusicPlayer,管理音乐播放,直接关联到摄像机处,方便获取波次生成脚本的实例。

这里插入一下,根据书上所说的,unity最基本的单元式组件,而且GetComponent<>()这一个泛化函数可以实例化组件然后直接使用,因此按照我的看法,就是我们可以获取到组件的实例,然后读懂组件里面的所有属性,就可以使得开发过程很方便,就例如这一个音乐源的组件,在书上并没有教过,我觉得它也只是一个组件,因此可以直接实例化然后修改内容。

基于以上观点去设计的背景音乐功能,这是我的一种看法。

那么废话不多说,在脚本中获取之前写好的波次脚本,就可以根据波次修改音乐内容。

然后关于AudioSource组件,是需要在游戏对象里面添加的,初始是不会自带的。

这一个组件相当于一个多功能的音响,我们需要在里面放入一张唱片,让他播放起来,所以具有一个特殊的类: AudioClip,这就是“唱片类”,里面可以存放你的mp3文件,放入之后就可以通过打开音响的开关.Play().如果想要换碟或者停止播放就关掉开关.Stop()。还有很多方法包含在内,有需要可以查找文章或者前往unity官网学习。

根据以上的基础,设计出音乐播放器的代码:

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

public class MusicPlayer : MonoBehaviour//这是一个播放音乐的脚本,放在摄像机里面
{
    [Header("设置")]
    public AudioSource musicPlayer;
    public int index;
    public AudioClip[] BackGroundMusic;
    public AudioClip[] BossMusic;
    public CactusSummoner cas;//记录是在摄像机里面的脚本
    public int maxNum;
    public bool isPlay;
    // Start is called before the first frame update
    void Start()
    {
        musicPlayer = gameObject.GetComponent<AudioSource>();//获取组件
        cas = gameObject.GetComponent<CactusSummoner>();//获取脚本,这个脚本里面有boss的信息
        index = 0;
        maxNum = 5;
        isPlay = false;
    }

    // Update is called once per frame
    void Update()
    {
        if (isPlay == false)//只有音乐变为未播放才会进入
        {
            if (musicPlayer.clip != null)
            {
                musicPlayer.Stop();//停止音乐
            }

            if (cas.isBoss == true)
            {
                musicPlayer.clip = BossMusic[cas.BossNum];//播放对应boss的音乐
                musicPlayer.Play();//播放音乐
                isPlay = true;
            }
            else
            {
                musicPlayer.clip = BackGroundMusic[index];
                musicPlayer.Play();
                isPlay = true;
            }
        }
    }
    public void IndexPlus()//循环播放
    {
        if (index >= maxNum)
        {
            index = 0;
        }
        else
        {
            index++;
        }
    }
}
 

以上就是这一个音乐播放的脚本了。

第五个Boss 

虽然设计了ui以及音乐播放器,我还是想要设计一个新的BOSS,这次设计的是泰拉瑞亚里面困难模式前最终boss--肉山,这一个boss其实挺无趣的,所以我也没有太大方式下手,而且我这一个游戏是相对运动的2d横板游戏,并不会实时更新地形,而泰拉瑞亚里面的肉山则是会一直追赶玩家的boss。没错我需要自己设计一些新的机制。

巫毒娃娃恶魔

在泰拉瑞亚里面,肉山的召唤需要将向导的巫毒娃娃丢入演讲,而这个娃娃由一种特殊的恶魔持有。我在想,要是只是让肉山出现,就好像有点太普通了,所以我想要加一个前置的东西,让玩家先击败带有巫毒娃娃的恶魔,让巫毒娃娃掉入岩浆里面,然后肉山出现。这样的演出也算是丰富了游戏内容。既然这样?那就来设计好这个演出吧!

首先恶魔的ai没什么,大部分是围着玩家转,时不时发射一把朝玩家飞去的镰刀。有一种让玩家觉得“这个boss怎么这么弱”的感觉,然后杀掉之后肉山突然出现。挺有意思。

这就是恶魔的代码:

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

public class DevilMove : MonoBehaviour
{
    [Header("设置")]
    public GameObject Projectile;//镰刀对象
    public GameObject Doll;
    public Vector3 Pos;//记录自身位置
    public GameObject Dino;//记录恐龙对象
    public Vector3 dinoPos;//记录恐龙对象的位置
    public float health;
    public Rigidbody rig;
    public Rigidbody proRig;//弹丸的刚体对象
    public float timeNow;
    public float timePast;//发射间隔
    public Vector3 summonPos;//记录生成位置
    public Vector3 StandNext;
    private float rat = 0f;
    private int facing = 1;//表示的是对象处于主角的前后方
    private int lastfacing = 1;
    public bool isDead;
    // Start is called before the first frame update
    void Start()
    {
        Pos = gameObject.transform.position;
        Dino = GameObject.Find("dino");//获取恐龙对象
        dinoPos = Dino.transform.position;
        health = 10f;
        timeNow = Time.time;
        timePast = 2f;
        rig = gameObject.GetComponent<Rigidbody>();
        summonPos = new Vector3(32f, 8f, 0);
        StandNext = Vector3.zero;
        gameObject.transform.position = summonPos;//得到初始位置
        Move();//进行第一次移动
    }

    // Update is called once per frame
    void Update()
    {
        if (health <= 0)
        {
            GameObject doll =  Instantiate(Doll);
            doll.transform.position = gameObject.transform.position;
            proRig = doll.GetComponent<Rigidbody>();
            proRig.velocity = Vector3.down * 3f;
            Destroy(gameObject);
        }
        Pos = gameObject.transform.position;
        FacingPlayer();
        if(Time.time - timeNow >= timePast)
        {
            Move();
            Attack();//攻击
        }
        if((Pos - StandNext).magnitude <= 0.2f)
        {
            rig.velocity = Vector3.zero;
        }
    }
    void Move()
    {
        dinoPos = Dino.transform.position;//获取恐龙目前坐标
        Vector3 tem = dinoPos;
        tem.x += Random.Range(-1, 2);
        tem.y += Random.Range(2, 4);//获取一个随机数
        StandNext = tem;
        Vector3 vel =tem - gameObject.transform.position;//获取一个速度
        vel.Normalize();//单位化
        rig.velocity = vel*3f;//获得一个速度
        timeNow = Time.time;//重置时间
    }
    void FacingPlayer()//面向玩家
    {
        Vector3 pos = gameObject.transform.position;//获取自己位置
        dinoPos = Dino.transform.position;
        if (pos.x - dinoPos.x <= 0)//表示在后面
        {
            facing = -1;//更改朝向
        }
        else if (pos.x - dinoPos.x > 0)//表示在前面
        {
            facing = 1;//更改朝向
        }

        if (facing != lastfacing)//两个朝向不一致
        {
            //print("trans aug");测试是否转角
            rat += lastfacing * 180f;
            gameObject.transform.rotation = Quaternion.Euler(0, rat, 0);//旋转180度
            lastfacing = facing;//更改上一次朝向
        }


    }
    void Attack()
    {
        dinoPos = Dino.transform.position;//获取恐龙坐标
        Vector3 vel = Vector3.zero;
        GameObject po = Instantiate(Projectile);
        proRig = po.GetComponent<Rigidbody>();
        po.transform.position = gameObject.transform.position;//获取坐标
        vel = dinoPos - po.transform.position;//获取一个速度
        vel.Normalize();
        proRig.velocity = vel * 5f;
    }
    void OnTriggerEnter(Collider collider)//触发器
    {
        if (collider.tag == "projectile")
        {
            GameObject tem = collider.gameObject;//获取游戏对象
            smilePro sp = tem.GetComponent<smilePro>();
            health -= sp.Damage;
        }
    }
}
 

这样恶魔就会一边移动一边发射镰刀了。

恶魔死后会掉落一个巫毒娃娃。然后召唤肉山。

肉山与恶魔的控制台 

自从蠕虫boss之后,我发现使用一个空对象作为“控制台”的思路能适用于很多情况,能做出很多类似于演出之类的效果。这次肉山的演出也是用一个控制台控制的。这个控制台将演出分为好几个等级,不同的等级进行不同的演出。第一等级:恶魔出现,第二等级:巫毒娃娃掉落,第三等级:肉山出现朝玩家快速冲刺,第四等级:肉山回到固定位置,开始朝玩家攻击,第五等级:肉山行动,第六等级:肉山死亡,控制台自毁

根据以上的思路,编写处以下的代码:

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

public class wallControler : MonoBehaviour
{
    [Header("设置")]
    public GameObject Devil;
    public GameObject wall;//分别记录三个对象
    public Vector3 wallSummonPos;
    public Rigidbody wallRig;
    public int level;
    public bool isDestroy;
    public int isRush;
    public GameObject wl;
    public Vector3 wallStand;
    // Start is called before the first frame update
    void Start()
    {
        level = 1;//等级一代表恶魔生成
        isDestroy = false;
        wallSummonPos = new Vector3(32.7f,6f,0);
        wallStand = new Vector3(30f, 6f, 0);
        Instantiate(Devil);//生成恶魔
    }

    // Update is called once per frame
    void Update()
    {
        if (level < 3)
        {
            Check();//等级小于三的时候进入检查
        }
        else if (level == 3)
        {
            WallSummon();
        }
        else if (level == 4)
        {
            Vector3 wal =wl.transform.position;
            if (wal.x <= 17.25f)
            {
                wl.transform.position = wallSummonPos;//回到原点
                wallRig.velocity = Vector3.left * 2f;
                level++;
            }
        }
        else if (level == 5)
        {
            if ((wl.transform.position - wallStand).magnitude <= 0.2f)
            {
                wallRig.velocity = Vector3.zero;
                level++;
            }
        }
        else if(level == 6)
        {
            GameObject wl = GameObject.Find("Wall(Clone)");
            if (wl == null)
            {
                Destroy(gameObject);
            }
        }
    }
    void Check()
    {
        GameObject de = GameObject.Find("Devil(Clone)");
        if (de == null&&level==1)//恶魔被消灭
        {
            level++;//等级加一
        }
        if (level == 2)
        {
            de = GameObject.Find("Doll(Clone)");
            if(de == null)
            {
                level++;
            }
        }
    }
    void WallSummon()//一个使得boss初始生成的方法
    {
        wl = Instantiate(wall);
        wl.transform.position = wallSummonPos;//获得生成坐标
        wallRig = wl.GetComponent<Rigidbody>();//获得刚体
        wallRig.velocity = Vector3.left * 20f;
        level++;
    }
}
 

 肉山行为

跟泰拉瑞亚本来的肉山行为类似的地方就是,都会冲向玩家。但是让玩家无故掉血这样的,可能有点可恶,因此我设计让肉山会生成一种小怪,会在玩家周围盘旋一段时间,要是玩家不小心触碰到他,就会将玩家牢牢固定住(无法移动),然后肉山就会朝玩家快速冲刺。强制玩家收到一次攻击。其他技能就是,肉山会发射激光,还有就是肉山会朝玩家目前位置冲刺,然后缓缓回到原点。这就是关于肉山最简单的设计了。

以下为小怪的代码,参考了玩家混乱的方式,直接将玩家脚本实例化,然后设置一个状态变量,要是为true就无法移动。同时朝肉山返回一个变量,让肉山冲刺。

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

public class hungerMove : MonoBehaviour
{
    [Header("设置")]
    public GameObject dino;
    public GameObject wall;
    public Rigidbody rig;
    public float timeNow;
    public float timePast;
    public float timeSum;
    public bool isCatch;
    // Start is called before the first frame update
    void Start()
    {
        dino = GameObject.Find("dino");
        wall = GameObject.Find("Wall(Clone)");
        rig = gameObject.GetComponent<Rigidbody>();
        timeNow = Time.time;
        timeSum = Time.time;
        isCatch = false;
        timePast = 2f;
        Move();
    }

    // Update is called once per frame
    void Update()
    {
        if(Time.time - timeSum >= 4f)
        {
            Dino dd = dino.GetComponent<Dino>();
            dd.isCatch = false;
            Destroy(gameObject);
        }
        if ((gameObject.transform.position - dino.transform.position).magnitude >= 0.2)
        {
            TrackPlayer();
        }
        if (isCatch == true)
        {
            rig.MovePosition(dino.transform.position);
        }
        if(Time.time - timeNow >= timePast)
        {
            Move();
            timeNow = Time.time;
        }
    }
    void OnTriggerEnter(Collider collider)//触发器
    {
        if (collider.tag == "dino")
        {
            rig.velocity = Vector3.zero;
            GameObject di = collider.gameObject;
            Dino dd = dino.GetComponent<Dino>();
            if (dd.isCatch == true)
            {
                return;
            }
            dd.isCatch = true;
            wallMove wal = wall.GetComponent<wallMove>();
            wal.Catch = true;
            isCatch = true;
        }
    }
    void TrackPlayer()//这个函数其实逻辑跟上面那个基本一致,应该可以用授权的方式写,但是我没有这样(不是好参考
    {
        Vector3 dinoPos = dino.transform.position;
        Vector3 wormPos = gameObject.transform.position;//获取玩家当前位置
        float length = (dinoPos - wormPos).magnitude;//获得长度
        float Ang = Mathf.Abs((dinoPos.y - wormPos.y) / length);//获得一个sin值
        float A2 = (Mathf.Asin(Ang) * Mathf.Rad2Deg);//反sin函数加上弧度制获得角度
        if (wormPos.y >= dinoPos.y)//假设蠕虫在所需要点的上方
        {
            A2 += 90f;//加上九十度
        }
        //在左边       
        //计算确切角度;
        if (wormPos.y <= dinoPos.y)//在下方需要修改
        {
            A2 = 90f - A2;
        }
        if (wormPos.x <= dinoPos.x)//在左边
        {
            gameObject.transform.rotation = Quaternion.Euler(0, 0, -A2);
        }
        else
        {
            gameObject.transform.rotation = Quaternion.Euler(0, 0, A2);
        }
    }
    void Move()
    {
        Vector3 dinoPos = dino.transform.position;
        dinoPos.x += Random.Range(-1, 2);
        dinoPos.y += Random.Range(1, 3);
        Vector3 vel = dinoPos - gameObject.transform.position;
        vel.Normalize();
        rig.velocity = vel * 5f;
    }
}
 

 这就是小怪的代码了。

这有一个会使得对象看向玩家的代码,我发现很多都需要这样的代码,我把它包装成一个独立脚本了:

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

public class PlayerTrack : MonoBehaviour
{
    [Header("设置")]
    public GameObject dino;
    public Vector3 dinoPos;
    // Start is called before the first frame update
    void Start()
    {
        dino = GameObject.Find("dino");
        dinoPos = dino.transform.position;
        TrackPlayer();
    }

    // Update is called once per frame
    void Update()
    {
        
    }
    void TrackPlayer()//眼睛紧跟着玩家
    {
        Vector3 eyePos = gameObject.transform.position;//获取眼睛当前位置
        dinoPos = dino.transform.position;//获取玩家坐标
        float length = (dinoPos - eyePos).magnitude;//获得长度
        float Ang = Mathf.Abs((dinoPos.y - eyePos.y) / length);//获得一个sin值
        float A2 = (Mathf.Asin(Ang) * Mathf.Rad2Deg);//反sin函数加上弧度制获得角度
        if (eyePos.y <= dinoPos.y)//假如在下方
        {
            A2 += 90f;//加上九十度
        }
        //在左边       
        //计算确切角度;
        if (eyePos.y >= dinoPos.y)//在上方需要修改
        {
            A2 = 90f - A2;
        }
        if (eyePos.x <= dinoPos.x)//在左边
        {
            gameObject.transform.rotation = Quaternion.Euler(0, 0, A2);
        }
        else
        {
            gameObject.transform.rotation = Quaternion.Euler(0, 0, -A2);
        }

    }
}
 

肉山本身的代码:

肉山的代码就跟上面说的一样,与之前设置的boss没有太多区别:

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

public class wallMove : MonoBehaviour//这里就是肉山boss的主要脚本
{
    [Header("设置")]
    public GameObject Hunger;//小弟,恶鬼
    public GameObject laser;//激光
    public GameObject dino;
    public Vector3 dinoPos;
    public float health;
    public Vector3 vel;
    public int roll;
    private bool isRush;
    public bool isBack;
    public float timeNow;
    public float timePast;
    public float laserTimePast;
    public float laserTimeNow;
    public Vector3 RushPos;
    private int laserNum;
    public bool Catch;//独特机制
    public bool dashBack;
    private bool dashNow;
    private Rigidbody rig;
    [Header("UI设置")]
    public TextMeshProUGUI bossLife;
    public GameObject LifeCount;
    // Start is called before the first frame update
    void Start()
    {
        dino = GameObject.Find("dino");//以下全为初始化设置
        dinoPos = dino.transform.position;
        health = 80f;
        vel = Vector3.zero;
        roll = 0;
        isRush = false;
        isBack = false;
        Catch = false;
        dashNow = false;
        dashBack = false;
        timeNow = Time.time;
        timePast = 2f;
        laserTimeNow = timeNow;
        laserTimePast = 0.2f;
        laserNum = 0;
        LifeCount = GameObject.Find("bossLife");
        rig = gameObject.GetComponent<Rigidbody>();//获取刚体对象
        bossLife = LifeCount.GetComponent<TextMeshProUGUI>();
        bossLife.text = "Wall : 100%";
    }

    // Update is called once per frame
    void Update()
    {
        UpDateUI();
        if (health <= 0)
        {
            bossLife.text = " ";
            Destroy(gameObject);
        }
        if (Catch == true)//玩家被抓住
        {
            Dash();//冲刺
        }
        if (Time.time - timeNow >= timePast&&Catch==false)
        {
            Move();
        }
    }
    void Move()
    {
        switch (roll)
        {
            case 0://第一个技能
                if (Time.time - laserTimeNow >= laserTimePast)
                {
                    laserTimeNow = Time.time;//重置时间
                    Vector3 laserPos = gameObject.transform.position;
                    laserPos.x -= 1.3f;laserPos.y += 2f;
                    GameObject la = Instantiate(laser);
                    la.transform.position = laserPos;
                    Rigidbody laR = la.GetComponent<Rigidbody>();
                    Vector3 vel = dino.transform.position - laserPos;
                    vel.Normalize();laR.velocity = vel*20f;
                    laserNum++;
                }
                if (laserNum >= 5f)
                {
                    laserNum = 0;
                    timeNow = Time.time;
                    laserTimeNow = Time.time;
                    roll = Random.Range(0, 3);
                }
                break;
            case 1://第二种攻击,生成小鬼
                for(int i = 0; i < 2; i++)
                {
                    GameObject hu = Instantiate(Hunger);
                    hu.transform.position = gameObject.transform.position;//获得boss位置
                    //hu有独立脚本无需要做其他处理
                }
                timeNow = Time.time;//重置时间
                roll = Random.Range(0, 3);
                break;
            case 2://朝玩家冲刺的
                if (isRush == false)
                {
                    isRush = true;
                    rig.velocity = Vector3.left * 10f;
                    RushPos = dino.transform.position;//获取一个方位
                }
                if(isRush == true)
                {
                    Vector3 pos = gameObject.transform.position;
                    if((pos.x - RushPos.x) <= 1f)
                    {
                        isBack = true;
                        rig.velocity = Vector3.zero;//速度下降为0
                        rig.velocity = Vector3.right * 5f;//回去原来的位置
                        RushPos = new Vector3(30f, 6f, 0);
                    }
                }
                if (isBack == true)
                {
                    if(((gameObject.transform.position - RushPos).magnitude) <= 0.2f)
                    {
                        rig.velocity = Vector3.zero;
                        isBack = false;isRush = false;
                        timeNow = Time.time;
                        roll = Random.Range(0, 3);
                    }
                }
                break;
            default:
                break;
        }
    }
    void Dash()
    {
        Vector3 pos = gameObject.transform.position;
        if (dashBack == true)
        {
            if (pos.x <= 30f)
            {
                rig.velocity = Vector3.zero;
                Catch = false;
                dashBack = false;
                dashNow = false;
                timeNow = Time.time;
                roll = 0;
                return;
            }
        }
        if (pos.x <= 17.25)
        {
            gameObject.transform.position = new Vector3(32.7f, 6f, 0);
            rig.velocity = Vector3.left * 5f;
            dashBack = true;
        }
        if (dashNow == false)
        {
            rig.velocity = Vector3.left * 20f;
            dashNow = true;
        }
    }
    void OnTriggerEnter(Collider collider)//触发器
    {
        if (collider.tag == "projectile")
        {
            GameObject tem = collider.gameObject;//获取游戏对象
            smilePro sp = tem.GetComponent<smilePro>();
            health -= sp.Damage;
        }
    }
    void UpDateUI()
    {
        string tem = "Wall : " + (int)((health / 80f)*100) + "%";
        bossLife.text = tem;
    }
   
}
 

 

 这样,三个新功能就设计好啦!!

以下是使用的贴图:

以下为实例场景:

以下为测试的完整视频:

(审核中)

单肉山的测试视频:

(审核中)

结语

终于完成本次练习啦,这次用了不少新的组件,我还会继续学习,不断添加新内容,感谢大家支持!

标签:Unity3d,背景音乐,google,gameObject,Vector3,transform,GameObject,position,public
From: https://blog.csdn.net/m0_67738084/article/details/136781229

相关文章

  • Unity3D 基础 05 场景加载
    Unity3D基础系列(第五期)场景配置首先,在资源文件夹里创建一个LoadScene场景,摆放一些物体,用来做初始场景。然后创建一个Stage文件夹,并创建两个场景Stage1、Stage2。两个Stage场景也可以简单布置一下,方便区分。接着,打开BuildSettings,把需要加载的场景添加到配置......
  • 小米澎湃操作系统(Hyper OS)下,如何获取谷歌安全码(Google Security Code)
    打开任易一个谷歌的应用,比如Google搜索(一般就叫Google),或者Youtube,或者GoogleAuthenticator,点击右上角的头像,然后点击“管理您的Google账号”,再点页面中上部的横栏里的“安全性”选项卡,往下滑,就能看到“安全码”选项,点击进入即可。  ......
  • 探索谷歌的秘密花园:Google文件系统GFS之旅(Google File System)
    文章目录......
  • Unity3D 基于ECS的AOI设计与实现详解
    EntityComponentSystem(ECS)是Unity3D引擎中的一种编程模式,它将游戏对象分解为实体(Entity)和组件(Component),以提高游戏性能和可维护性。对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白,也有一些正在从事游戏开发的技术大佬,欢迎你来交流学习。在游戏开发中,Are......
  • Unity3D 客户端网络角色的操作与行为分离设计详解
    在网络游戏中,客户端网络角色的操作与行为分离设计是非常重要的,它可以提高游戏的可维护性和扩展性,同时也可以提升游戏的性能和用户体验。对啦!这里有个游戏开发交流小组里面聚集了一帮热爱学习游戏的零基础小白,也有一些正在从事游戏开发的技术大佬,欢迎你来交流学习。在本文中,我们......
  • Google高级搜索
    工欲善其事,必先利其器无论程序员也好,还是普通人都要能够利用好搜索引擎,以下是关于Google搜索的一些小的技巧和方法。表格总结+同AND,搜索包含多个关键词的结果示例or或者搜索+引擎-不包含减号后面词的页面搜索OR引擎“”精确匹配搜索-百度*模糊搜索,星......
  • Google广告账户解封
    请简要说明你的业务*Lifo是一家初创企业,业务主要涉及两个方向,方向1:面向网红提供个人IP电商网站一站式运营服务,服务内容主要包含,电商网站搭建与运营,商品创意设计与生产,仓储与物流配送,订单与客户管理等。每网红都是独立域名电商网站。方向2:面向NFT机构与NFT购买用户,打造NFT数字......
  • Unity3D外包团队 北京动点软件:优秀的软件公司 如何与客户建立长期合作关系
    2024年作为优秀的软件公司在确保客户满意方面需要采取一系列措施,以下是一些关键步骤:深入理解客户需求:首要任务是充分理解客户的需求。外包公司应该花时间与客户沟通,详细了解他们的业务目标、项目需求、预期结果以及任何特殊要求。这有助于建立良好的合作关系,并确保提供的......
  • 一键开启 GPU 闲置模式,基于函数计算低成本部署 Google Gemma 模型服务
    作者:王骜本文介绍如何使用函数计算GPU实例闲置模式低成本、快速的部署GoogleGemma模型服务。背景信息Google在2024年02月21日正式推出了自家的首个开源模型族Gemma,并同时上架了四个大型语言模型,提供了2B和7B两种参数规模的版本,每种都包含了预训练版本(base模......
  • 揭秘Google Gemini:AI界的多模态革命者与ChatGPT-4的较量
    在人工智能的快速发展浪潮中,GoogleDeepMind的最新力作——Gemini,以其多模态的超凡能力,正引领着AI技术的新一轮革命。本文将深入探讨Gemini的核心特性、不同版本的特点,以及它与ChatGPT-4的对比优势和差异。一、Gemini简介AI的新纪元GoogleGemini,作为DeepMind的旗舰产......