模板建站与仿站哪个更好,北京注册公司地址可以是住宅吗,郑州网站建设方案服务,国内优秀网站设计提示#xff1a;文章写完后#xff0c;目录可以自动生成#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、第一个代表性场景 1.制作敌人僵尸跳跳虫更多敌人2.制作敌人阿斯匹德更多可交互对象3.制作敌人孵化虫和它的孩子二、第二个代表性场景 1.制作更多敌人2.制作… 提示文章写完后目录可以自动生成如何生成可参考右边的帮助文档 文章目录 前言一、第一个代表性场景 1.制作敌人僵尸跳跳虫更多敌人2.制作敌人阿斯匹德更多可交互对象3.制作敌人孵化虫和它的孩子二、第二个代表性场景 1.制作更多敌人2.制作更多可交互对象总结 前言 hello大家好久没见之所以隔了这么久才更新并不是因为我又放弃了这个项目而是接下来要制作的工作太忙碌了每次我都花了很长的时间解决完一个部分然后就没力气打开CSDN写文章就直接睡觉去了现在终于有时间整理下我这半个月都做了什么内容。 废话少说接下来我将继续介绍我做的几个代表性场景可能你会说“怎么标题还和上期一模一样”那当然是没办法的事情毕竟一期讲完这么多场景敌人可交互对象你没看睡着我都快写睡着了OK我们接着来制作更多地图更多敌人更多可交互对象 另外我的Github已经更新了想要查看最新的内容话请到我的Github主页下载工程吧
GitHub - ForestDango/Hollow-Knight-Demo: A new Hollow Knight Demo after 2 years! 一、第一个代表性场景 1.制作敌人僵尸跳跳虫更多敌人 我突然找到一个有四个新类型敌人的场景让我们先来介绍这四少吧但首先还是先搭建好场景 可能看到这里你还不知道这对应的是游戏里的哪个场景但只要我加上场景景色一切将豁然开朗 往上走去鹿角站往右走去打苍蝇之母因此记得添加好对应的TransitionPoint。
我们先来制作最简单的僵尸跳跳虫做好相对应的tk2dsprite和tk2dspriteAnimator。 添加相对应的脚本 老朋友Attack Range攻击距离 落地状态下的灰尘粒子系统Dust: 创建一个名字为“Zombie Swipe”的playmakerFSM然后老规矩贴出事件和变量 逐个讲状态
初始化阶段 准备阶段逐帧判断攻击距离和可视范围内 判断玩家位置 攻击准备阶段 起飞阶段 落地阶段 冷却阶段 回到空闲阶段 重置Walker脚本的行为 这样一个简单跳跳僵尸虫就完成了。
2.制作敌人阿斯匹德更多可交互对象 然后是制作敌人阿斯匹德注意这个不是折磨玩家的原始阿斯匹德而是只会喷一个方向的
首先添加好tk2dsprite和tk2dSpriteAnimator: 长开火和短开火的动画 添加好相应的脚本 除此之外我们还要制作攻击用的子弹 我们先来制作玩家离开攻击距离的playmakerFSM 这里会设置Spitter的playmakerFSM里面的bool变量unalert Range 以及设置bool变量Can See Hero 回到阿斯匹德spitter中我们首先创建一个之前讲过的playmakerFSM叫flyer_receive_direction_msg。这个我之前讲蚊子那期用过就是接收不同方向信息的
然后才是我们的重点“spitter” FSM 初始化状态播放音效和动画确认初始时的朝向空闲状态漫无目的的IdleBuzz通过Alert Range New来判断是否在攻击距离里并check Can See Hero. 如果满足上述两个条件直接进入Alert状态 径直向玩家飞去 判断位置并射线检测 再飞行一小段距离朝向玩家 准备开火阶段 设置发射的子弹朝向玩家设置好速度 当玩家离开攻击距离后回到Unalert Frame状态下一帧再回到Idle状态 这里我们来创建子弹预制体 新建一个脚本名字叫EnemyBullet.cs
using System.Collections;
using UnityEngine;[RequireComponent(typeof(Rigidbody2D))]
public class EnemyBullet : MonoBehaviour
{public float scaleMin 1.15f;public float scaleMax 1.45f;private float scale;[Space]public float stretchFactor 1.2f;public float stretchMinX 0.75f;public float stretchMaxY 1.75f;[Space]public AudioSource audioSourcePrefab;public AudioEvent impactSound;private bool active;private Rigidbody2D body;private tk2dSpriteAnimator anim;private Collider2D col;private void Awake(){body GetComponentRigidbody2D();anim GetComponenttk2dSpriteAnimator();col GetComponentCollider2D();}private void OnEnable(){active true;scale Random.Range(scaleMin, scaleMax);col.enabled true;body.isKinematic false;body.velocity Vector2.zero;body.angularVelocity 0f;anim.Play(Idle);}private void Update(){if (active){float rotation Random.Range(body.velocity.y,body.velocity.x) * 57.295776f;transform.SetRotation2D(rotation);float num 1f - body.velocity.magnitude * stretchFactor * 0.01f;float num2 1f body.velocity.magnitude * stretchFactor * 0.01f;if (num2 stretchMinX){num2 stretchMinX;}if (num stretchMaxY){num stretchMaxY;}num * scale;num2 * scale;transform.localScale new Vector3(num2, num, transform.localScale.z);}}private void OnCollisionEnter2D(Collision2D collision){if (active){active false;StartCoroutine(Collision(collision.GetSafeContact().Normal, true));}}private void OnTriggerEnter2D(Collider2D collision){if(active collision.tag HeroBox){active false;StartCoroutine(Collision(Vector2.zero, false));}}public void OrbitShieldHit(Transform shield){if (active){active false;Vector2 normal transform.position - shield.position;normal.Normalize();StartCoroutine(Collision(normal, true));}}private IEnumerator Collision(Vector2 normal, bool doRotation){transform.localScale new Vector3(scale, scale, transform.localScale.z);body.isKinematic true;body.velocity Vector2.zero;body.angularVelocity 0f;tk2dSpriteAnimationClip impactAnim anim.GetClipByName(Impact);anim.Play(impactAnim);if (!doRotation || (normal.y 0.75f Mathf.Abs(normal.x) 0.5f)){transform.SetRotation2D(0f);}else if (normal.y 0.75f Mathf.Abs(normal.x) 0.5f){transform.SetRotation2D(180f);}else if (normal.x 0.75f Mathf.Abs(normal.y) 0.5f){transform.SetRotation2D(270f);}else if (normal.x 0.75f Mathf.Abs(normal.y) 0.5f){transform.SetRotation2D(90f);}impactSound.SpawnAndPlayOneShot(audioSourcePrefab, transform.position);yield return null;col.enabled false;yield return new WaitForSeconds((impactAnim.frames.Length - 1) / impactAnim.fps);Destroy(gameObject);//TODO:}}回到Unity编辑器添加好对应的参数,
最后再添加一个子对象一个小小的亮灯 3.制作敌人孵化虫和它的孩子
这个敌人我忘了叫什么名字了暂且叫它孵化虫吧先添加上tk2dsprite和tk2dspriteanimator: 它的攻击方式只有一种那就是生下小虫子然后小虫子来攻击玩家子对象只需要一个Alert Range New 上面的playmakerFSM除了之前讲过的flyer_receive_direction_msg还有就是“Hatcher” 这里给它最多生五个孩子 在开始前我们可以在场景中偏离核心区域的地方预生成它的孩子并把它们关在笼子里面别到处乱跑 注意添加好tag这里我先预生成了15只虫子宝宝并让它们待在这个隐形笼子里面。 如上面阿斯匹德一样Idle状态 检查是否已经生够了到达最大可生成数量 来点生下来的音效设置好生下来的位置为宝宝的playmakerFSM发送事件SPAWN 这里有几个自定义playmakerFSM行为脚本我好像忘记说了
using System;
using UnityEngine;namespace HutongGames.PlayMaker.Actions
{[ActionCategory(ActionCategory.Audio)][Tooltip(Instantiate an Audio Player object and play a oneshot sound via its Audio Source.)]public class AudioPlayerOneShot : FsmStateAction{[RequiredField][CheckForComponent(typeof(AudioSource))][Tooltip(The object to spawn. Select Audio Player prefab.)]public FsmGameObject audioPlayer;[RequiredField][Tooltip(Object to use as the spawn point of Audio Player)]public FsmGameObject spawnPoint;[CompoundArray(Audio Clips, Audio Clip, Weight)]public AudioClip[] audioClips;[HasFloatSlider(0f, 1f)]public FsmFloat[] weights;public FsmFloat pitchMin;public FsmFloat pitchMax;public FsmFloat volume;public FsmFloat delay;public FsmGameObject storePlayer;private AudioSource audio;private float timer;public override void Reset(){spawnPoint null;audioClips new AudioClip[3];weights new FsmFloat[]{1f,1f,1f};pitchMin 1f;pitchMax 1f;volume 1f;timer 0f;}public override void OnEnter(){timer 0f;if(delay.Value 0f){DoPlayRandomClip();Finish();}}public override void OnUpdate(){if(delay.Value 0f){if(timer delay.Value){timer Time.deltaTime;return;}DoPlayRandomClip();Finish();} }private void DoPlayRandomClip(){if (audioClips.Length 0)return;GameObject value audioPlayer.Value;Vector3 position spawnPoint.Value.transform.position;Vector3 up Vector3.up;//TODO:这行记得要改因为我还没做对象池GameObject gameObject UnityEngine.Object.Instantiate(audioPlayer.Value, position, Quaternion.Euler(up));audio gameObject.GetComponentAudioSource();int randomWeightIndex ActionHelpers.GetRandomWeightedIndex(weights);if(randomWeightIndex ! -1){AudioClip audioClip audioClips[randomWeightIndex];if(audioClip ! null){float pitch UnityEngine.Random.Range(pitchMin.Value, pitchMax.Value);audio.pitch pitch;audio.PlayOneShot(audioClip);}}audio.volume volume.Value;}public AudioPlayerOneShot(){pitchMin 1f;pitchMax 2f;}}}using UnityEngine;namespace HutongGames.PlayMaker.Actions
{[ActionCategory(ActionCategory.GameObject)][Tooltip(Spawns a random amount of chosen GameObject from global pool and fires them off in random directions.)]public class FlingObjectsFromGlobalPool : RigidBody2dActionBase{[RequiredField][Tooltip(GameObject to spawn.)]public FsmGameObject gameObject;[Tooltip(GameObject to spawn at (optional).)]public FsmGameObject spawnPoint;[Tooltip(Position. If a Spawn Point is defined, this is used as a local offset from the Spawn Point position.)]public FsmVector3 position;[Tooltip(Minimum amount of objects to be spawned.)]public FsmInt spawnMin;[Tooltip(Maximum amount of objects to be spawned.)]public FsmInt spawnMax;[Tooltip(Minimum speed objects are fired at.)]public FsmFloat speedMin;[Tooltip(Maximum speed objects are fired at.)]public FsmFloat speedMax;[Tooltip(Minimum angle objects are fired at.)]public FsmFloat angleMin;[Tooltip(Maximum angle objects are fired at.)]public FsmFloat angleMax;[Tooltip(Randomises spawn points of objects within this range. Leave as 0 and all objects will spawn at same point.)]public FsmFloat originVariationX;public FsmFloat originVariationY;[Tooltip(Optional: Name of FSM on object you want to send an event to after spawn)]public FsmString FSM;[Tooltip(Optional: Event you want to send to object after spawn)]public FsmString FSMEvent;private float vectorX;private float vectorY;private bool originAdjusted;public override void Reset(){gameObject null;spawnPoint null;position new FsmVector3{UseVariable true};spawnMin null;spawnMax null;speedMin null;speedMax null;angleMin null;angleMax null;originVariationX null;originVariationY null;FSM new FsmString{UseVariable true};FSMEvent new FsmString{UseVariable true};}public override void OnEnter(){if (gameObject.Value ! null){Vector3 a Vector3.zero;Vector3 zero Vector3.zero;if (spawnPoint.Value ! null){a spawnPoint.Value.transform.position;if (!position.IsNone){a position.Value;}}else if (!position.IsNone){a position.Value;}int num Random.Range(spawnMin.Value, spawnMax.Value 1);for (int i 1; i num; i){//TODO:以后创造完对象池后记得替换掉GameObject gameObject GameObject.Instantiate(this.gameObject.Value, a, Quaternion.Euler(zero));float x gameObject.transform.position.x;float y gameObject.transform.position.y;float z gameObject.transform.position.z;if (originVariationX ! null){x gameObject.transform.position.x Random.Range(-originVariationX.Value, originVariationX.Value);originAdjusted true;}if (originVariationY ! null){y gameObject.transform.position.y Random.Range(-originVariationY.Value, originVariationY.Value);originAdjusted true;}if (originAdjusted){gameObject.transform.position new Vector3(x, y, z);}base.CacheRigidBody2d(gameObject);float num2 Random.Range(speedMin.Value, speedMax.Value);float num3 Random.Range(angleMin.Value, angleMax.Value);vectorX num2 * Mathf.Cos(num3 * 0.017453292f);vectorY num2 * Mathf.Sin(num3 * 0.017453292f);Vector2 velocity;velocity.x vectorX;velocity.y vectorY;rb2d.velocity velocity;if (!FSM.IsNone){FSMUtility.LocateFSM(gameObject, FSM.Value).SendEvent(FSMEvent.Value);}}}Finish();}}}二、第二个代表性场景
1.制作敌人沃姆Worm
说起来你看到这名字可能想不起来这是啥怪物其实就是遗忘十字路中恶心玩家的那个路障 首先是灰尘粒子系统 这个石头也是粒子系统 这个也是粒子系统石头区别在于上面那个是Idle状态下播放的粒子系统而这个是在Burst状态下播放的 这个虫子属于是既能伤害玩家又能伤害敌人的因此添加上DamageHero和DamageEnemy两个脚本 这里我们把将骨钉攻击那期的Nail Slash里面的playmakerfsm“damages_enemy”也给它安排上 还有自己的Worm Control: 向上中 缩回去 已经缩回地里
是否开启burst rocks的particlesystem Burst的时候就在这里开启伤害和Collider 自定义行为脚本如下
using UnityEngine;namespace HutongGames.PlayMaker.Actions
{[ActionCategory(Particle System)][Tooltip(Set particle emission on or off on an object with a particle emitter)]public class SetParticleEmission : FsmStateAction{[RequiredField][Tooltip(The particle emitting GameObject)]public FsmOwnerDefault gameObject;public FsmBool emission;public override void Reset(){gameObject null;emission false;}public override void OnEnter(){if (gameObject ! null){GameObject ownerDefaultTarget Fsm.GetOwnerDefaultTarget(gameObject);if (ownerDefaultTarget ! null){ownerDefaultTarget.GetComponentParticleSystem().enableEmission emission.Value;}}Finish();}}
}using HutongGames.PlayMaker;
using UnityEngine;[ActionCategory(Hollow Knight)]
public class SetDamageHeroAmount : FsmStateAction
{[UIHint(UIHint.Variable)]public FsmOwnerDefault target;public FsmInt damageDealt;public override void Reset(){target new FsmOwnerDefault();damageDealt null;}public override void OnEnter(){GameObject safe target.GetSafe(this);if(safe ! null){DamageHero component safe.GetComponentDamageHero();if(component ! null !damageDealt.IsNone){component.damageDealt damageDealt.Value;}}base.Finish();}}至此我们制作了一个流动的循环。
2.制作可交互对象
其实主要就是这些杆子我们用脚本breakable.cs来制作 using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Breakable : MonoBehaviour,IHitResponder
{private Collider2D bodyCollider;[Tooltip(Renderer which presents the undestroyed object.)][SerializeField] private Renderer wholeRenderer;[Tooltip(List of child game objects which also represent the whole object.)][SerializeField] public GameObject[] wholeParts;[Tooltip(List of child game objects which represent remnants that remain static after destruction.)][SerializeField] private GameObject[] remnantParts;[SerializeField] private ListGameObject debrisParts;[SerializeField] private float angleOffset -60f;[Tooltip(Breakables behind this threshold are inert.)][SerializeField] private float inertBackgroundThreshold;[Tooltip(Breakables in front of this threshold are inert.)][SerializeField] private float inertForegroundThreshold;[Tooltip(Breakable effects are spawned at this offset.)][SerializeField] private Vector3 effectOffset;[Tooltip(Prefab to spawn for audio.)][SerializeField] private AudioSource audioSourcePrefab;[Tooltip(Table of audio clips to play upon break.)][SerializeField] private AudioEvent breakAudioEvent;[Tooltip(Table of audio clips to play upon break.)][SerializeField] private RandomAudioClipTable breakAudioClipTable;[Tooltip(Prefab to spawn when hit from a non-down angle.)][SerializeField] private Transform dustHitRegularPrefab;[Tooltip(Prefab to spawn when hit from a down angle.)][SerializeField] private Transform dustHitDownPrefab;[Tooltip(Prefab to spawn when hit from a down angle.)][SerializeField] private float flingSpeedMin;[Tooltip(Prefab to spawn when hit from a down angle.)][SerializeField] private float flingSpeedMax;[Tooltip(Strike effect prefab to spawn.)][SerializeField] private Transform strikeEffectPrefab;[Tooltip(Nail hit prefab to spawn.)][SerializeField] private Transform nailHitEffectPrefab;[Tooltip(Spell hit effect prefab to spawn.)][SerializeField] private Transform spellHitEffectPrefab;[Tooltip(Object to send HIT event to.)][SerializeField] private GameObject hitEventReciever;[Tooltip(Forward break effect to sibling FSMs.)][SerializeField] private bool forwardBreakEvent;[Space]public Probability.ProbabilityGameObject[] containingParticles;public FlingObject[] flingObjectRegister;private bool isBroken;private void Awake(){bodyCollider GetComponentCollider2D();}protected void Reset(){inertBackgroundThreshold 1f;inertForegroundThreshold -1f;effectOffset new Vector3(0f, 0.5f, 0f);flingSpeedMin 10f;flingSpeedMax 17f;}protected void Start(){CreateAdditionalDebrisParts(debrisParts);float z transform.position.z;if(z inertBackgroundThreshold || z inertForegroundThreshold){BoxCollider2D component GetComponentBoxCollider2D();if(component ! null){component.enabled false;}Destroy(this);return;}for (int i 0; i remnantParts.Length; i){GameObject gameObject remnantParts[i];if(gameObject ! null gameObject.activeSelf){gameObject.SetActive(false);}}angleOffset * Mathf.Sign(transform.localScale.x);}protected virtual void CreateAdditionalDebrisParts(ListGameObject debrisParts){}public void Hit(HitInstance damageInstance){if (isBroken){return;}Debug.LogFormat(Breakable Take Hit);float impactAngle damageInstance.Direction;float num damageInstance.MagnitudeMultiplier;if(damageInstance.AttackType AttackTypes.Spell){Instantiate(spellHitEffectPrefab, base.transform.position, Quaternion.identity).SetPositionZ(0.0031f);}else{if (damageInstance.AttackType ! AttackTypes.Nail damageInstance.AttackType ! AttackTypes.Generic){impactAngle 90f;num 1f;}Instantiate(strikeEffectPrefab, base.transform.position,Quaternion.identity);Vector3 position (damageInstance.Source.transform.position base.transform.position) * 0.5f;SpawnNailHitEffect(nailHitEffectPrefab, position, impactAngle);}int cardinalDirection DirectionUtils.GetCardinalDirection(damageInstance.Direction);Transform transform dustHitRegularPrefab;float flingAngleMin;float flingAngleMax;Vector3 euler;if (cardinalDirection 2){angleOffset * -1f;flingAngleMin 120f;flingAngleMax 160f;euler new Vector3(180f, 90f, 270f);}else if (cardinalDirection 0){flingAngleMin 30f;flingAngleMax 70f;euler new Vector3(0f, 90f, 270f);}else if (cardinalDirection 1){angleOffset 0f;flingAngleMin 70f;flingAngleMax 110f;num * 1.5f;euler new Vector3(270f, 90f, 270f);}else{angleOffset 0f;flingAngleMin 160f;flingAngleMax 380f;transform dustHitDownPrefab;euler new Vector3(-72.5f, -180f, -180f);}if(transform ! null){Instantiate(transform, transform.position effectOffset, Quaternion.Euler(euler));}Break(flingAngleMin, flingAngleMax, num);}private static Transform SpawnNailHitEffect(Transform nailHitEffectPrefab, Vector3 position, float impactAngle){if (nailHitEffectPrefab null)return null;int cardinalDirection DirectionUtils.GetCardinalDirection(impactAngle);float y 1.5f;float minInclusive;float maxInclusive;if (cardinalDirection 3){minInclusive 270f;maxInclusive 290f;}else if (cardinalDirection 1){minInclusive 70f;maxInclusive 110f;}else{minInclusive 340f;maxInclusive 380f;}float x (cardinalDirection 2) ? -1.5f : 1.5f;Transform transform Instantiate(nailHitEffectPrefab,position,Quaternion.identity);Vector3 eulerAngles transform.eulerAngles;eulerAngles.z Random.Range(minInclusive, maxInclusive);transform.eulerAngles eulerAngles;Vector3 localScale transform.localScale;localScale.x x;localScale.y y;transform.localScale localScale;return transform;}public void Break(float flingAngleMin, float flingAngleMax, float impactMultiplier){if (isBroken)return;SetStaticPartsActivation(true);for (int i 0; i debrisParts.Count; i){GameObject gameObject debrisParts[i];if (gameObject null){Debug.LogErrorFormat(this, Unassigned debris part in {0}, new object[]{this});}else{gameObject.SetActive(true);gameObject.transform.SetRotationZ(gameObject.transform.localEulerAngles.z angleOffset);Rigidbody2D component gameObject.GetComponentRigidbody2D();if (component ! null){float num Random.Range(flingAngleMin, flingAngleMax);Vector2 a new Vector2(Mathf.Cos(num * 0.017453292f), Mathf.Sin(num * 0.017453292f));float d Random.Range(flingSpeedMin, flingSpeedMax) * impactMultiplier;component.velocity a * d;}}}if (containingParticles.Length ! 0){GameObject gameObject2 Probability.GetRandomGameObjectByProbability(containingParticles);if (gameObject2){if (gameObject2.transform.parent ! transform){FlingObject flingObject null;foreach (FlingObject flingObject2 in flingObjectRegister){if (flingObject2.referenceObject gameObject2){flingObject flingObject2;break;}}if (flingObject ! null){flingObject.Fling(transform.position);}else{gameObject2 Instantiate(gameObject2, transform.position, Quaternion.identity);}}gameObject2.SetActive(true);}}breakAudioEvent.SpawnAndPlayOneShot(audioSourcePrefab, transform.position);breakAudioClipTable.SpawnAndPlayOneShot(audioSourcePrefab, transform.position);if (hitEventReciever ! null){FSMUtility.SendEventToGameObject(hitEventReciever, HIT, false);}if (forwardBreakEvent){FSMUtility.SendEventToGameObject(gameObject, BREAK, false);}GameObject gameObject3 GameObject.FindGameObjectWithTag(CameraParent);if (gameObject3 ! null){PlayMakerFSM playMakerFSM PlayMakerFSM.FindFsmOnGameObject(gameObject3, CameraShake);if(playMakerFSM ! null){playMakerFSM.SendEvent(EnemyKillShake);}}wholeRenderer.enabled false;bodyCollider.enabled false;isBroken true;}private void SetStaticPartsActivation(bool v){}[System.Serializable]public class FlingObject{public GameObject referenceObject;[Space]public int spawnMin;public int spawnMax;public float speedMin;public float speedMax;public float angleMin;public float angleMax;public Vector2 originVariation;public FlingObject(){spawnMin 25;spawnMax 35;speedMin 9f;speedMax 20f;angleMin 20f;angleMax 160f;originVariation new Vector2(0.5f, 0.5f);}public void Fling(Vector3 origin){if (!referenceObject){return;}int num Random.Range(spawnMin, spawnMax 1);for (int i 0; i num; i){//TODO:Object PoolGameObject gameObject Instantiate(referenceObject);if (gameObject){gameObject.transform.position origin new Vector3(Random.Range(-originVariation.x, originVariation.x), Random.Range(-originVariation.y, originVariation.y), 0f);float num2 Random.Range(speedMin, speedMax);float num3 Random.Range(angleMin, angleMax);float x num2 * Mathf.Cos(num3 * 0.017453292f);float y num2 * Mathf.Sin(num3 * 0.017453292f);Vector2 force new Vector2(x, y);Rigidbody2D component gameObject.GetComponentRigidbody2D();if (component){component.AddForce(force, ForceMode2D.Impulse);}}}}}
}其三个子对象一个是杆的顶部top一个是杆的底部base,最后一个是破坏后蹦出来的石头particlesystem 制作好一个后我们就可以照此制作更多的这种可破坏的杆子Pole了 还有这种可破坏的雕塑原理都是一样的只不过这个没有头部只有底部而且有两个粒子系统 三、第三个代表性场景 这个夭折了因为CSDN提示我上传的图片到达上限了这我是没想到的没办法这一集只能分为上下两期来讲了而且下期我将讲述一个非常劲爆的敌人感兴趣的话就等我一两个小时把内容整理完成发出来吧。 md我没想到CSDN有规矩24小时内只能上传300张图片喜提一天冷却时间大伙只能等我明天再来把这篇和下一篇文章写完了。
总结 终于过了一天的坐牢期可以发图片出来了我就把这一期的效果图展示在这里吧。 再来看看阿斯匹德的效果 再来看看孵化虫Hatcher 然后再来看看沃姆worm的效果