谷歌小恐龙代码(谷歌小恐龙代码修改)

上一篇文章中,我没有设计boss,但是设计了一个比较简单的武器系统,使得玩家具有了攻击手段,由于时间不足,所以没有搞太深入。这次继续设计敌人对象,因为发现这个游戏实例的背景比较单调,所以去wiki里面找了一些背景图片,简单做了一个背景切换的功能对象。还有就是,嵌入式那篇文章我说想要搞什么锁链组件,最后发现不适用于我想制作的东西。所以放弃了,而且在开发过程中发现了一个2d图形谷歌小恐龙代码开发的一个关键组件---SpriteRendererÿ 谷歌小恐龙代码0c;可以修改对象所显示的2d图像,非常实用,本次练习也用了很多跟这个组件有关的功能。那么开始这次练习。

由于觉得游戏实例背景一片白,十分单调,所以设计了一个背景切换的功能,在击杀boss之后会切换到下一个boss有关的背景。但是因为时间原因,本来打算想把小怪也重新设计一次的(说实话,确实可以,下个星期会尝试一下)。本次设计只由背景切换的脚本。

逻辑很简单,首先创建一个空的GameObject,然后对其添加SpriteRenderer组件,以及一个名为backGround的脚本。脚本内容为,包含场景贴图的sprite对象,spr渲染器对象,以及一些判定的定义等,update中不断测试是否到达了击杀boss之后的波次---(wave-1)%5=0&&numofsummon==0.检测之后修改判定,调用trans函数,trans函数由+1,-1,控制对于sprite的透明度,把原来的背景透明度将为0,然后再把下一个背景透明度拉高,最后完成切换。

以下为切换的代码:

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

public class BackGround : MonoBehaviour
{
? ? [Header("设置")]
? ? public Sprite[] spB;//记录背景
? ? public GameObject cam;
? ? public int index;//目前背景数
? ? public float maxAl;
? ? public bool isChange;
? ? public int tr;
? ? // Start is called before the first frame update
? ? void Start()
? ? {
? ? ? ? index = 0;
? ? ? ? cam = GameObject.Find("MainCamera");//获取摄像头,目的是其中的脚本
? ? ? ? isChange = false;
? ? ? ? tr = -1;
? ? }

? ? // Update is called once per frame
? ? void Update()
? ? {
? ? ? ? Check();
? ? ? ? if (isChange == true)
? ? ? ? {
? ? ? ? ? ? Trans();
? ? ? ? }
? ? }
? ? void Check()
? ? {
? ? ? ? CactusSummoner cas = cam.GetComponent<CactusSummoner>();//获取脚本
? ? ? ? if ((cas.wave-1) % 5f == 0&&isChange==false&&cas.numOfSummon == 0&&cas.wave!=1)
? ? ? ? {
? ? ? ? ? ? IndexPlus();//递增index
? ? ? ? ? ? isChange = true;
? ? ? ? }
? ? }
? ? void IndexPlus()
? ? {
? ? ? ? if (index >= 4)//根据地图贴图数决定
? ? ? ? {
? ? ? ? ? ? index = 0;
? ? ? ? }
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? index++;
? ? ? ? }
? ? }
? ? void Trans()
? ? {
? ? ? ? SpriteRenderer spr = gameObject.GetComponent<SpriteRenderer>();//获取2d渲染器组件
? ? ? ? Color coltrans = spr.color;//获取颜色
? ? ? ? coltrans.a += 0.001f * (float)tr;
? ? ? ? spr.color = coltrans;
? ? ? ? if (coltrans.a <= 0)
? ? ? ? {
? ? ? ? ? ? tr *= -1;
? ? ? ? ? ? spr.sprite = spB[index];
? ? ? ? ? ? Color tem = spr.color;
? ? ? ? ? ? tem.a = 0f;
? ? ? ? ? ? spr.color = tem;
? ? ? ? }
? ? ? ? print(coltrans.a);
? ? ? ? if (coltrans.a >=maxAl&&tr==1)
? ? ? ? {
? ? ? ? ? ? isChange = false;
? ? ? ? ? ? tr *= -1;
? ? ? ? }
? ? }
}
?

本次设计的新敌人依然是来自泰拉瑞亚里的敌人。(因为泰拉wiki好抠图)世界吞噬者,这是一个蠕虫类敌人,正因如此一开始我才说想用锁链去实现他,但是最后发现2d贴图的旋转似乎无法到达我的预期,所以我取消了这个想法。而且,一开始我的想法是用一个空对象作为他的父对象,然后再把这个boss的关节一点一点拼上去,不得不说,这个想法还是很笨的,而且也让后面的一些行为难以实现,属于是吃力不讨好那种。所以我更改了我的想法!

这里提一下对于这个敌人我的想法--首先仿照游戏本家的怪物设计,世界吞噬者会从地里对玩家进行突击,并且会不时吐出口水攻击玩家,这个是非常简单的。这个boss的一大特色在于,如果玩家将它拦腰截断,也就是攻击了他的其中一个关节,而不是头部,这个关节死亡之后就会把上下两端作为独立个体行动,就会有一种一条断开就变成两条的效果。这次我对这个boss的设计做重点就在于此。

关于如何实现这个特点:

首先,我创建了一个空对象---wormControl,用于控制整个蠕虫的整体,比如生成,以及上面的一变二的控制,由于wiki里提供了头,身体,尾巴,三个贴图,我就可以利用上文提到的SpriteRenderer进行贴图修改。剩下的只需要交给不断检测null就可以了,因为在生成蠕虫的时候,会把每一个关节都放入一个nowWorm的GameObject数组里面。在update内不断检测,是否存在断裂,再根据断裂的情况给上下两个分配不同的贴图。同时已经修改过的关节不会再修改)

以下是这个wormControl的代码:

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

public class wormHead : MonoBehaviour//*此处应该时放置在其他地方而不是头部
{
? ? [Header("设置")]//放在头部会导致头部被消灭就会使得行为错乱
? ? public GameObject[] wormPre;//对于蠕虫的对象脚本
? ? public Sprite[] wormSp;//记录贴图,这是一个用来控制蠕虫生成以及控制蠕虫一些机制的脚本
? ? public Vector3 SummonPos;//记录生成位置
? ? public SpriteRenderer spR;//便于在蠕虫断开时改变头
? ? public float timeNow;
? ? public float timeSum;
? ? public GameObject[] nowWorm;//记录现在的虫子节,方便出现断裂时进行响应
? ? public bool[] isChange;//一个记录是否已经改变过状态的数组
? ? public bool isDestroy;
? ? // Start is called before the first frame update
? ? void Start()
? ? {
? ? ? ? isDestroy = false;
? ? ? ? timeNow = Time.time;
? ? ? ? timeSum = Time.time;//记录初始时间
? ? ? ? gameObject.transform.position = new Vector3(25, 2.5f, 0);
? ? ? ? SummonPos = gameObject.transform.position;//第二节一开始的位置
? ? ? ? for(int i = 0; i < 15; i++)//生成蠕虫
? ? ? ? {
? ? ? ? ? ? GameObject wp = null;
? ? ? ? ? ? if (i==14)//最后一节
? ? ? ? ? ? {
? ? ? ? ? ? ? ? wp = Instantiate(wormPre[2]);
? ? ? ? ? ? ? ? wp.transform.position = SummonPos;
? ? ? ? ? ? }
? ? ? ? ? ? else if (i == 0)//生成头部
? ? ? ? ? ? {
? ? ? ? ? ? ? ? wp = Instantiate(wormPre[0]);
? ? ? ? ? ? ? ? wp.transform.position = SummonPos;
? ? ? ? ? ? ? ? SummonPos.y -= 0.5f;
? ? ? ? ? ? }
? ? ? ? ? ? else//普通关节
? ? ? ? ? ? {
? ? ? ? ? ? ? ? wp = Instantiate(wormPre[1]);
? ? ? ? ? ? ? ? wp.transform.position = SummonPos;
? ? ? ? ? ? ? ? SummonPos.y -= 0.5f;
? ? ? ? ? ? }
? ? ? ? ? ? nowWorm[i+1] = wp;//记录现在的虫子关节
? ? ? ? }
? ? ? ? isChange[0] = true; isChange[16]=true;//将哨兵的设置改为1
? ? ? ? isChange[1] = true; isChange[15] = true;//此处为头部以及尾部,无法再此处修改
? ? }

? ? // Update is called once per frame
? ? void Update()
? ? {
? ? ? ? Check();
? ? ? ? if (isDestroy == true)
? ? ? ? {
? ? ? ? ? ? Destroy(gameObject);//摧毁生成器
? ? ? ? }
? ? }
? ? void Check()//检查是否存在断裂
? ? {
? ? ? ? for(int i = 1; i < 15; i++)
? ? ? ? {
? ? ? ? ? ? if (nowWorm[i] == null)//被消灭,也就是断裂了
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if (nowWorm[i - 1] != null && isChange[i-1] ==false)//未改变且不是null
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? spR = nowWorm[i - 1].GetComponent<SpriteRenderer>();//获取2d渲染器组件
? ? ? ? ? ? ? ? ? ? spR.sprite = wormSp[2];//前面的对象的2d图像修改为尾巴
? ? ? ? ? ? ? ? ? ? isChange[i - 1] = true;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? if (nowWorm[i + 1] != null && isChange[i+1]==false)
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? spR = nowWorm[i +1].GetComponent<SpriteRenderer>();
? ? ? ? ? ? ? ? ? ? spR .sprite = wormSp[0];
? ? ? ? ? ? ? ? ? ? isChange[i + 1] = true;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? ? ? if (nowWorm[i] != null)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? if (nowWorm[i + 1] == null && nowWorm[i - 1] == null)//表示该个体已经独立,获得新的行动模式
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? spR = nowWorm[i].GetComponent<SpriteRenderer>();//获取2d渲染器组件
? ? ? ? ? ? ? ? ? ? spR.sprite = wormSp[3];//2d图像更改为独立个体
? ? ? ? ? ? ? ? ? ? wormmove wor = nowWorm[i].GetComponent<wormmove>();//获取该个体脚本
? ? ? ? ? ? ? ? ? ? wor.isAlone = true;//修改属性
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? isDestroy = true;
? ? ? ? for(int i = 1; i < 15; i++)
? ? ? ? {
? ? ? ? ? ? if (nowWorm[i] != null)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? isDestroy = false;
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
?

对了,关于nowWorm数组我设置了哨兵,因为我发现,假如头部或者尾部断裂会数组溢出,所以添加了哨兵也就是数组头尾为null,主体在中间部分以防止访问溢出等问题.?

?后面有整体的实例的测试视频

对于这个蠕虫boss的行为,根据原来的行为,我稍作简单的修改,首先,boss不会图突击玩家,而是会根据六个点位上下循环进行移动,移动的同时会朝玩家发射弹丸攻击,同时,在前后都没有关节会变成小飞虫,不断朝玩家进行冲刺。

这个实现非常简单。同时由于相对运动的机制,只要每一个关节保持相同的距离,速度一致,就可以看起来像一整个整体在运动,因此,所有关节都共用同一个脚本。

但是这样就会导致,即使从中间切断,分裂出来的两个个体也只会朝着相同的方向行动,由于时间问题就保留了这个特性。(其实可以在WormControl里面对不同的关节进行同步,但是本次练习没有实现)

以下为Boss的代码:

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

public class wormmove : MonoBehaviour//蠕虫移动脚本
{
? ? [Header("设置")]
? ? public GameObject Dino;
? ? public Sprite littleWorm;
? ? public Rigidbody rig;
? ? public Vector3[] standNextUp = new Vector3[]//只有头才可以选择坐标
? ? {
? ? ? ? new Vector3(19f,8.5f,0),new Vector3(25f,8.5f,0),new Vector3(30.85f,8.5f,0)
? ? };
? ? public Vector3[] standNextDown = new Vector3[]
? ? {
? ? ? ? new Vector3(19f,3f,0),new Vector3(25f,3f,0),new Vector3(30.85f,3f,0)
? ? };//为了实现交叉移动选择了两个数组作为基准
? ? public float health;
? ? public Vector3 standHead;//表示下一个点的位置
? ? public int nextIndex;//记录下一个移动次序
? ? public bool UpOrDown;
? ? public GameObject projectile;//发射的弹丸
? ? public float timePast;
? ? public float timeNow;
? ? public bool isAlone;
? ? public bool isTrack;
? ? private Vector3 trans;
? ? private bool isRoll;
? ? private bool trackPlayer;
? ? // Start is called before the first frame update
? ? void Start()
? ? {
? ? ? ? Dino = GameObject.Find("dino");
? ? ? ? rig = gameObject.GetComponent<Rigidbody>();//获取刚体变量
? ? ? ? health = 2f;
? ? ? ? standHead = Vector3.zero;
? ? ? ? nextIndex = 1;
? ? ? ? UpOrDown = true;//一开始从初始位置往上走
? ? ? ? timePast = 2f;//发射弹丸时间间隔
? ? ? ? standHead = standNextUp[nextIndex];//设置初始位置
? ? ? ? rig.velocity = Vector3.up * 5f;
? ? ? ? timeNow = Time.time;
? ? ? ? isAlone = false;
? ? ? ? isTrack = false;
? ? ? ? isRoll = false;
? ? ? ? trackPlayer = true;
? ? ? ? trans = Vector3.zero;
? ? }

? ? // Update is called once per frame
? ? void Update()
? ? {
? ? ? ? if (health <= 0)
? ? ? ? {
? ? ? ? ? ? Destroy(gameObject);
? ? ? ? }
? ? ? ? if (isAlone == false)
? ? ? ? {
? ? ? ? ? ? Move();
? ? ? ? ? ? if (Time.time - timeNow >= timePast)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? timeNow = Time.time;
? ? ? ? ? ? ? ? ShotProjectile();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? Alone();//执行独立个体的运动
? ? ? ? }
? ? }
? ? void IndexPlus()//增加次序
? ? {
? ? ? ? if (nextIndex >= 2)
? ? ? ? {
? ? ? ? ? ? nextIndex = 0;//f防止超过
? ? ? ? }
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? nextIndex++;//递增
? ? ? ? }
? ? ? ? UpOrDown = !UpOrDown;
? ? }
? ? void Move()//运动时
? ? {
? ? ? ? if ((gameObject.transform.position - standHead).magnitude <= 0.1f)//基本到达目标点
? ? ? ? {
? ? ? ? ? ? IndexPlus();//增加计数
? ? ? ? ? ? if (UpOrDown == true)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //print("changeUp");
? ? ? ? ? ? ? ? standHead = standNextUp[nextIndex];//获得下一个点
? ? ? ? ? ? }
? ? ? ? ? ? else
? ? ? ? ? ? {
? ? ? ? ? ? ? ? //print("changeDown");
? ? ? ? ? ? ? ? standHead = standNextDown[nextIndex];//获得下一个点
? ? ? ? ? ? }
? ? ? ? ? ? TrackPoint();//看向目标点
? ? ? ? ? ? Vector3 vel = standHead - gameObject.transform.position;
? ? ? ? ? ? vel.Normalize();rig.velocity = vel * 5f;
? ? ? ? }
? ? }
? ? void TrackPoint()//看向对应点s
? ? {
? ? ? ? Vector3 wormPos = gameObject.transform.position;//获取玩家当前位置
? ? ? ? float length = (standHead - wormPos).magnitude;//获得长度
? ? ? ? float Ang = Mathf.Abs((standHead.y - wormPos.y) / length);//获得一个sin值
? ? ? ? float A2 = (Mathf.Asin(Ang) * Mathf.Rad2Deg);//反sin函数加上弧度制获得角度
? ? ? ? if (wormPos.y >= standHead.y)//假设蠕虫在所需要点的上方
? ? ? ? {
? ? ? ? ? ? A2 += 90f;//加上九十度
? ? ? ? }
? ? ? ? //在左边 ? ? ??
? ? ? ? //计算确切角度;
? ? ? ? if (wormPos.y <= standHead.y)//在下方需要修改
? ? ? ? {
? ? ? ? ? ? A2 = 90f - A2;
? ? ? ? }
? ? ? ? if (wormPos.x <= standHead.x)//在左边
? ? ? ? {
? ? ? ? ? ? gameObject.transform.rotation = Quaternion.Euler(0, 0, -A2);
? ? ? ? }
? ? ? ? else
? ? ? ? {
? ? ? ? ? ? gameObject.transform.rotation = Quaternion.Euler(0, 0, A2);
? ? ? ? }

? ? }
? ? 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 Alone()//当只有一个关节,则改为其他行动模式
? ? {
? ? ? ? if(isRoll == false)
? ? ? ? {
? ? ? ? ? ? Vector3 dinoPos = Dino.transform.position;//获取恐龙坐标
? ? ? ? ? ? dinoPos.y += Random.Range(1, 3); dinoPos.x += Random.Range(-1, 2);//获取一个随机的坐标
? ? ? ? ? ? trans = dinoPos;
? ? ? ? ? ? isRoll = true;//更新是否由确定坐标
? ? ? ? }
? ? ? ? if (isTrack == false)
? ? ? ? {
? ? ? ? ? ? Vector3 vel = trans - gameObject.transform.position;//前往随机坐标
? ? ? ? ? ? vel.Normalize(); vel *= 5f;
? ? ? ? ? ? rig.velocity = vel;
? ? ? ? ? ? isTrack = true;
? ? ? ? }
? ? ? ? if(isTrack == true)
? ? ? ? {
? ? ? ? ? ? if((gameObject.transform.position - trans).magnitude <= 0.1f)//靠近了所需点
? ? ? ? ? ? {
? ? ? ? ? ? ? ? Vector3 vel = Dino.transform.position - trans;
? ? ? ? ? ? ? ? vel.Normalize();vel *= 10f;
? ? ? ? ? ? ? ? rig.velocity = vel;
? ? ? ? ? ? ? ? trackPlayer = false;
? ? ? ? ? ? }
? ? ? ? ? ? if(trackPlayer == true)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? TrackPlayer();
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? Vector3 tem = gameObject.transform.position;
? ? ? ? if(tem.y <= 0f || tem.y >= 10f || tem.x <= 15f || tem.x >= 40f)
? ? ? ? {
? ? ? ? ? ? isRoll = false;
? ? ? ? ? ? isTrack = false;
? ? ? ? ? ? trackPlayer = true;
? ? ? ? }
? ? }
? ? void ShotProjectile()//发射唾液
? ? {
? ? ? ? Vector3 dinoPos = Dino.transform.position;//获取恐龙坐标
? ? ? ? Vector3 vel = dinoPos - gameObject.transform.position;//获取速度方向
? ? ? ? vel.Normalize();vel *= 10f;
? ? ? ? GameObject pp = Instantiate(projectile);
? ? ? ? pp.transform.position = gameObject.transform.position;
? ? ? ? Rigidbody proRig = pp.GetComponent<Rigidbody>();
? ? ? ? proRig.velocity = vel;
? ? }
? ? void OnTriggerEnter(Collider collider)//触发器
? ? {
? ? ? ? if (collider.tag == "projectile")
? ? ? ? {
? ? ? ? ? ? GameObject tem = collider.gameObject;//获取游戏对象
? ? ? ? ? ? smilePro sp = tem.GetComponent<smilePro>();
? ? ? ? ? ? health -= sp.Damage;
? ? ? ? }
? ? }
}
?

以上就是本次设计的全部内容:

这是使用的boss贴图:?谷歌小恐龙代码

这是本次练习完成后的实例场景:

以下为整体测试的视频,方便测试,除了本次设计的boss以外,之前设计的boss都会在5s后自动销毁。

好了,本次练习到此结束,本次利用了spriteRendere的基本功能实现了不少功能。我受益匪浅,我还会继续更新unity有关的练习,感谢大家支持!谢谢!

转载请说明出处 内容投诉内容投诉
九幽软件 » 谷歌小恐龙代码(谷歌小恐龙代码修改)