制作更多的Defender:
之前我们创建了一个向日葵和一个仙人掌,今天我们多创建两个
首先是一个老头Gnome,我们让它的功能和仙人掌一样,所以我会尽量快点讲完,
需要给它三个脚本Defender,Shooter,Health
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Defender : MonoBehaviour
{
[SerializeField] int starCost = 100;
public int GetStarCost()
{
return starCost;
}
public void AddStars(int amount)
{
FindObjectOfType<StarsDisplay>().AddStars(amount);
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Shooter : MonoBehaviour
{
[SerializeField] GameObject projectTile;
[SerializeField] GameObject gun;
AttackSpawner myLaneSpawner;
Animator animator;
private void Start()
{
animator = GetComponent<Animator>();
SetLaneSpawner();
}
private void Update()
{
if(IsAttackerInLand())
{
animator.SetBool("isAttacking", true);
}
else
{
animator.SetBool("isAttacking", false);
}
}
private void SetLaneSpawner()
{
AttackSpawner[] spawners = FindObjectsOfType<AttackSpawner>();
//找到这行路的所有敌人
foreach(var spawner in spawners)
{
//判断是不是在我们这一行
bool IsCloseEnough = (Mathf.Abs( spawner.transform.position.y - transform.position.y ) <= Mathf.Epsilon);
if (IsCloseEnough)
{
myLaneSpawner = spawner; //找到我这条路的生成敌人
}
}
}
private bool IsAttackerInLand()
{
//如果我这条路上的敌人数量小于等于0return false
if(myLaneSpawner.transform.childCount <= 0)
{
return false;
}
else
{
return true;
}
}
public void Fire()
{
Instantiate(projectTile, gun.transform.position, transform.rotation); //生成子弹
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Health : MonoBehaviour
{
[SerializeField] float health = 100f;
[SerializeField] GameObject deathVFX;
public void DealDamage(float damage)
{
health -= damage;
if(health <= 0)
{
TriggerDeathVFX();
Destroy(gameObject);
}
}
//生成爆炸特效
private void TriggerDeathVFX()
{
if (!deathVFX) return;
GameObject deathVFXObject = Instantiate(deathVFX, transform.position, transform.rotation);
Destroy(deathVFXObject, 1f); //1秒后销毁生成的爆炸特效
}
}
然后给它碰撞框和动画并把参数都填上去后我们给它一个空对象Body创建组件Sprite Renderer。通过改变它的Sprite来制造动画。
斧头的Prefab如下
动画就让他旋转365°
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Projectile : MonoBehaviour
{
[SerializeField] float speed = 1f;
[SerializeField] float damage = 50f;
void Update()
{
transform.Translate(Vector2.right * speed * Time.deltaTime);
}
private void OnTriggerEnter2D(Collider2D other)
{
var health = other.GetComponent<Health>();
var attacker = other.GetComponent<Attacker>();
if(attacker && health)
{
health.DealDamage(damage);
Destroy(gameObject);
}
}
}
然后我们来创建一个墓碑GraveStone,相当于高坚果,它的血量非常厚可以挡住很久
除了前面的脚本还要给他一个独特的脚本,但只是给之后我们创建的敌人识别的
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GraveStone : MonoBehaviour
{
private void OnTriggerStay2D(Collider2D other)
{
Attacker attacker = other.GetComponent<Attacker>();
if (attacker)
{
}
}
}
给它做个动画就稍微改变一下它的Scale值
最后,别忘了把他们放到我们之前创建的Quad中
创建敌人:
在创建新的敌人之前,我们需要让敌人都实现能吃植物的动画,因此我们创建一个鳄鱼的吃植物动画Lizard Attack把对应的素材拖进ANimation
我们选择添加动画事件,当执行那一帧的时候植物掉血。
吃植物时候速度为0
这个是一口多少血
创建一个Lizard给它
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lizard : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D other)
{
GameObject otherGameObject = other.gameObject;
if (otherGameObject.GetComponent<Defender>())
{
GetComponent<Attacker>().Attack(otherGameObject);
}
}
}
Attacker脚本更新后如下:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Attacker : MonoBehaviour
{
GameObject currentTarget;
[Range(0, 5)]
float currentSpeed = 1f;
private void Awake()
{
FindObjectOfType<LevelController>().AttackerSpawn();
}
private void OnDestroy()
{
LevelController level = FindObjectOfType<LevelController>();
if (level != null)
{
level.AttackerKilled();
}
}
void Update()
{
transform.Translate(Vector2.left * currentSpeed * Time.deltaTime);
UpdateAnimationState();
}
private void UpdateAnimationState()
{
if (!currentTarget)
{
GetComponent<Animator>().SetBool("isAttacking", false);
}
}
public void SetMovementSpeed(float speed)
{
currentSpeed = speed;
}
public void Attack(GameObject target)
{
GetComponent<Animator>().SetBool("isAttacking", true); //播放吃植物动画
currentTarget = target;//锁定植物
}
public void StrikeCurrentTarget(float damage)
{
if (!currentTarget) return;
Health health = currentTarget.GetComponent<Health>();
if (health)
{
health.DealDamage(damage);//扣植物的血
}
}
}
在完成了鳄鱼后,我们要创建一个特别的狐狸敌人:
同样先给他设置好动画
给它添加好脚本后添加参数再创建一个名字叫fox的脚本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Fox : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D other)
{
GameObject otherGameObject = other.gameObject;
if (otherGameObject.GetComponent<GraveStone>()) //当遇到gravestone时他会跳过去
{
GetComponent<Animator>().SetTrigger("JumpTrigger");
}
else if (otherGameObject.GetComponent<Defender>()) //而其它的他会吃掉
{
GetComponent<Attacker>().Attack(otherGameObject);
}
}
}
同样我们也要为他创建动画事件
游戏效果:
可见跑的跑跳的跳,鳄鱼直接开吃,最下排的生成敌人给老头两斧头扔死了