学习目标:
上期的水平大伙看到我已经写好了Enemy和Player的脚本了,现在就把脚本教给大伙,话不多说搞的不丑
学习内容:
首先是Player的脚本(之前没发现CSDN有这个代码段的,我的我的)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
[Header("玩家移动")]
[SerializeField] float ySpeed = 10f;
[SerializeField] float xSpeed = 10f;
[SerializeField] float padding = 1f;
[Header("Play Health")]
[SerializeField] int health = 500;
[Header("ProjectTile")]
[SerializeField] GameObject laserPrefab;
[SerializeField] float projectTileSpeed = 10f;
[SerializeField] float projectTileFiringPeriod = 0.1f;
//战机在屏幕能移动的坐标
float xMin;
float xMax;
float yMin;
float yMax;
//协程的编程是指在不堵塞主线程的情况下执行某些特定的函数
Coroutine fireCoroutine;
void Start()
{
SetUpMoveBoundaries();
}
private void SetUpMoveBoundaries()
{
Camera gameCamera = Camera.main;
//之前的视频说过,Camera.main.ViewportToWorldPoint()是将摄像机视角的坐标转化为世界坐标然后padding是防止战机出屏幕边缘
xMin = gameCamera.ViewportToWorldPoint(new Vector3(0, 0, 0)).x + padding;
xMax = gameCamera.ViewportToWorldPoint(new Vector3(1, 0, 0)).x - padding;
yMin = gameCamera.ViewportToWorldPoint(new Vector3(0, 0, 0)).y + padding;
yMax = gameCamera.ViewportToWorldPoint(new Vector3(0, 1, 0)).y - padding;
}
void Update()
{
Move();
Fire();
}
private void Move()
{
//Input Manager上两个监控键盘上WSAD按键而生成-1到1值的
var deltaY = Input.GetAxis("Vertical") * Time.deltaTime * ySpeed;
var deltaX = Input.GetAxis("Horizontal") * Time.deltaTime * xSpeed;
// Debug.Log(deltaX);
//限制移动范围
var newXPos = Mathf.Clamp(transform.position.x + deltaX, xMin, xMax);
var newYPos = Mathf.Clamp(transform.position.y + deltaY, yMin, yMax);
transform.position = new Vector2(newXPos,newYPos);
}
private void Fire()
{
if (Input.GetButtonDown("Fire1"))
{
fireCoroutine = StartCoroutine(FireContinuously());
}
if (Input.GetButtonUp("Fire1"))//这个Fire1也是Input Manager上的
{
StopCoroutine(fireCoroutine); //暂停某个协程
// StopAllCoroutines();
}
}
//协程函数是用关键字迭代器IEnumerator而且一定要用yield关键词返回
IEnumerator FireContinuously()
{
while (true)
{
GameObject laser = Instantiate(laserPrefab, transform.position, Quaternion.identity) as GameObject; //生成子弹
laser.GetComponent<Rigidbody2D>().velocity = new Vector2(0, projectTileSpeed); //给子弹一个向上的力
yield return new WaitForSeconds(projectTileFiringPeriod); //下一颗子弹发生的间隔时间
}
}
private void OnTriggerEnter2D(Collider2D other)
{
DamageDealer damageDealer = other.gameObject.GetComponent<DamageDealer>();
if (!damageDealer) { return; }
ProcessHit(damageDealer);
}
private void ProcessHit(DamageDealer damageDealer)
{
health -= damageDealer.GetDamage(); //减去收到的伤害
damageDealer.Hit();
if (health <= 0)
{
Destroy(gameObject); //生命值为小于等于0就销毁
}
}
}
代码中我说的是Input Manager可以在菜单栏上找到
Positive表示的是正向
Negative则是反向的,对于Horizontal 和 Vertical来说,反向意味着是0到-1的负值
DamageDealer是处理收到伤害的时候触发的脚本
内容如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DamageDealer : MonoBehaviour
{
[SerializeField] int damage = 100;
public int GetDamage()
{
return damage;
}
public void Hit()
{
Destroy(gameObject);
}
}
这个脚本使挂载到子弹Laser的游戏对象上的,下一期再讲
然后最后是Enemy脚本
内容如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
[SerializeField] float health = 100f;
[SerializeField] float shotCounter;
[SerializeField] float minTimeBetweenShots = 0.2f;
[SerializeField] float maxTimeBetweenShot = 1.5f;
[SerializeField] GameObject projecttile;
[SerializeField] float projecttileSpeed = 10f;
void Start()
{
shotCounter = Random.Range(minTimeBetweenShots, maxTimeBetweenShot);
}
void Update()
{
CountDownAndShoot();
}
private void CountDownAndShoot()
{
shotCounter -= Time.deltaTime; //计时器,用来当计时器小于等于0时重置发射时间并执行发射函数
if(shotCounter <= 0)
{
Fire();
shotCounter = Random.Range(minTimeBetweenShots, maxTimeBetweenShot);
}
}
private void Fire()
{
GameObject laser = Instantiate(projecttile, transform.position, Quaternion.identity) as GameObject;//生成子弹并给它一个向下的力,因为和主角方向反过来的
laser.GetComponent<Rigidbody2D>().velocity = new Vector2(0, -projecttileSpeed);
}
private void OnTriggerEnter2D(Collider2D other)
{
DamageDealer damageDealer = other.gameObject.GetComponent<DamageDealer>();
if (!damageDealer) { return; }
ProcessHit(damageDealer); //同样也是伤害处理的函数
}
private void ProcessHit(DamageDealer damageDealer)
{
health -= damageDealer.GetDamage();
damageDealer.Hit();
if (health <= 0)
{
Destroy(gameObject);
}
}
}
学习产出:
别忘了设置好脚本上的参数,以及将我们创建的子弹预设体拖上去
挂载好以后,我们就可以实现Player的上下左右移动以及按住鼠标发射子弹和敌人也发射子弹