植物大战僵尸的制作
[点击直达github](1zero0/PlantVSZombies: 学习制作植物大战僵尸并熟悉Unity)
1.创建项目
点击右上角新项目
选择2D(built-In Render Pipeline)(红色箭头),修改自己项目的名字(蓝色箭头),选择自己想要的地址(绿色箭头)
2.项目
将资源包(红色箭头)拖入到Assets(蓝色箭头)中并等待一段时间。
2.1 导入素材
如下图中,Audio就是音效Images就是相关的所有图片,其中Music中包含的就是背景音乐,随后点击右下角Import
导入后就会在这里生成一个Audio文件夹(红色箭头)和Images文件夹(蓝色箭头)
随后点开Audio中的Music和Sound文件夹,会看到导入的音频,随便选一个,然后在右边可以点击播放(红色箭头)
注:如果右边没有如下图的ch 1和ch 2可以点击AssetBundle上的bgm就会弹出如图所示的样子
3.项目制作
3.1 导入背景
再Background中找到这个白天场景(红色箭头)
Pixels Per Unit指的是图片导入到unity中的一个单位转换,60像素转换为一米。(再unity中一个格子代表一米)
随后将场景拖入到左侧的Scene中
随后点击左上角Scene右侧的Game(游戏视角),并选择Full HD(1920x1080)
随后可以通过右边的X和Y进行场景的位置改动
随后导入卡片,以便于种植,植物再Card中
因为植物卡片需要卡片槽(用于放置植物卡片),这里先找到卡片槽,在UI中
- 随后在上面Hierarchy中右键
- 选择UI
- 选择Image
- (先双击Canvas聚焦)先点击Image
- 选择右侧Image中的Source Image,
在弹出的窗口中选择卡片槽
随后点击Image中的Set Native Size
随后将卡片槽拖拽到左上角的位置
然后通过Game来确认它的最终位置,还是通过右侧Pos X和Pox Y进行左右和上下的移动
- 选择定位
- 选择左上角
3.2 植物卡片
先像上面一样创建一个Image
随后将新建的图层拉到卡片槽的位置,并找到向日葵(可种植状态)
随后复制一个图层并选择灰色的向日葵(不可种植状态)
随后再次复制一个图层,并选择黑色图层(冷却状态中)
- 选择Color
- 选择透明度
随后在Image Type中选择Simple
随后在选择Fill Method中的Vertical(上下)(Horizontal:水平,Radial 360:圆圈型360度,其余两个同理)
随后选择Fill Origin中将Bottom(从下往上)改为Top(从上往下)
随后将这三张图片分到一个组中
并将其命名为CardTemplate,并将下面的卡片分别命名为CardLight(可种植),CardGray(不可种植),CardMask(冷却中)
随后我们要创建一个文件夹来存放这些卡片,即将CardTemplate文件拖入到我们新建的Prefabs中
随后将卡槽和植物卡片共同组建一个父类(也可以将植物卡片放到卡槽下),并起名为CardListUI
这里要记得将CardListUI也定位于左上角
3.3 为植物卡片添加脚本使之达到各种状态
先创建一个新的文件夹Scripts用于存放脚本
- 点击CardTemplate
- 点击Add Component
- 输入Card,回车(两次,随后等待创建好)
随后将新建的Card脚本拖入到Scripts中
随后双击点开Card,在内部写入代码
enum CardState
{
Cooling,
WaitingSun,
Ready
}
public class Card : MonoBehaviour
{
// 冷却 可以被点击 不可用
private CardState cardState = CardState.Cooling;
//要控制植物卡片的状态,就要先获取三种状态
public GameObject cardLight;
public GameObject cardGary;
public Image cardMask;
private void Update()
{
switch (cardState)
{
case CardState.Cooling:
CoolingUpdate();
break;
case CardState.WaitingSun:
WaitingSunUpdate();
break;
case CardState.Ready:
ReadyUpdate();
break;
default:
break;
}
}
// 卡片等待动作,首先要确定卡片的时间,即冷却时间,通过计时器来实现,通过剩余时间(冷却时间-计时器时间)/一个冷却时TransitionToWaitingSun()间生成的一个比例来给FillAmount达到一个控制效果,这样就可以使得FillAmount达到一个逐步地减少。当冷却时间到了之后就会执行TransitionToWaitingSun()转换到一个等待阳光的状态,然后就会转到WaitingSunUpdate()状态
void CoolingUpdate()
{
cdTimer += Time.deltaTime;
cardMask.fillAmount = (cdTime - cdTimer) / cdTime; // 剩余时间的比例
if (cdTimer >= cdTime)
{
TransitionToWaitingSun();
}
}
void WaitingSunUpdate()
{
}
void ReadyUpdate()
{
}
void TransitionToWaitingSun()
{
cardState = CardState.WaitingSun; // 先改变植物卡片的状态(冷却状态改为灰色状态)
// 植物状态的启用和禁用
cardLight.SetActive(false); // 将植物卡片亮禁用
cardGary.SetActive(true); // 植物卡片灰启用
cardMask.gameObject.SetActive(false); // 将等待状态禁用
}
}
保存之后回到unity,将三种状态拖入到对应的地方(如图中红色箭头)
3.4 阳光的计数
因为植物的种植需要阳光,所以先创建一个Empty,并改名为Manager
随后点击右侧Add Component然后添加一个Sun Manager脚本,并双击点开
随后先将SunManager拖入到Scripts中,随后新建文件夹Manager,并将SunManager拖入其中
随后编写SunManager的代码,
public static SunManager Instance { get; private set; }
private void Awake() // 进行赋值
{
Instance = this;
}
[SerializeField] // 加上一个序列化的标签,以便于可以随时改变
private int sunPoint; // 使用私有不会让值在外面随便改变
public int SunPoint // 用来获取阳光值
{
get { return sunPoint; }
}
然后回到card中,将时间私有化,以免随便被换掉并创建序列化标签便于改变。
[SerializeField]
private float cdTime = 2; // 冷却时间
private float cdTimer = 0; // 计时器,从零开始(可以从零增加到2 ,也可以从最大减少到零)
设置一个植物的需要的阳光的值
[SerializeField]
private int needSunPoint = 50;
再回到如果需要的阳光值小于已有的阳光值,则植物卡片状态变为准备状态
void WaitingSunUpdate()
{
if (needSunPoint <= SunManager.Instance.SunPoint)
{
TransitionToReady();
}
}
编写转换为准备状态的代码(高亮改为启用,等待阳光状态改为禁用,等待冷却时间保持不变)
void TransitionToReady()
{
cardState = CardState.Ready;
cardLight.SetActive(true);
cardGary.SetActive(false);
cardMask.gameObject.SetActive(false);
}
3.5 准备状态(等待点击状态)
因为在准备状态可能会因为种植别的植物而使得阳光不够,所以要先确定阳光是否充足,先将阳光不够时候的代码写出
void ReadyUpdate()
{
if (needSunPoint > SunManager.Instance.SunPoint)
{
TransitionToWaitingSun();
}
}
接下来给高亮时候添加一个button
随后在card中添加一个方法用来处理自身被点击的事件,
public void Onclick()
{
}
并回到unity中将Card Template拖入到Select Object中
随后点击右侧No Function选择Card中的Onclick
随后回到代码中,因为在点击前我们可能会遇到阳光不够的情况,所以先做一个判断,如果阳光不够则直接返回,不做任何处理
public void Onclick()
{
if (needSunPoint > SunManager.Instance.SunPoint) return;
}
再写一个转换为冷却时间的方法即Cooling方法
void TransitionCooling()
{
cardState = CardState.Cooling;
cdTimer = 0;
cardLight.SetActive(false);
cardGary.SetActive(true);
cardMask.gameObject.SetActive(true);
}
随后将此方法放入到点击事件中
public void Onclick()
{
if (needSunPoint > SunManager.Instance.SunPoint) return;
// TODO:消耗阳光值,并进行种植
TransitionCooling();
}
随后回到unity中并将CardTemplate复制两个,并将其分别改名为CardSunFlower和CardPeaShooter
随后选择CardLight,点击右侧的Source Image选择peashooter的图片,CardGary同理,CardMask不做改动
3.6 开发阳光值的消耗和更新
在CardListUI中创建一个Text-TextMeshPro(之后改名为SunPointText)
随后选中Text(TMP)并将其拖到适合位置并改变大小
随后点击Text(TMP)改变其中字体大小并悬着上下左右居中
将里面的内容改为300
改变字体颜色为黑色,并改变字体
呈现如下效果
随后在SunManager代码中增加public TextMeshProUGUI sunPointText;
代码,并在unity中进行手动拖拽将SunPointText拖进去
随后在SunManager代码块中增加更新阳光的代码
public void UpdateSunPointText()
{
sunPointText.text = sunPoint.ToString();
}
随后在上面编写一个阳光开始的代码,并将UpdateSunPointText()放入其中
private void Start()
{
UpdateSunPointText();
}
编写一个阳光减少并更新数值的代码
public void SubSun(int point)
{
sunPoint -= point;
UpdateSunPointText();
}
随后进入Cards中,在点击(Onclick)方法中增加方法
public void Onclick()
{
if (needSunPoint > SunManager.Instance.SunPoint) return;
// TODO:消耗阳光值,并进行种植
SunManager.Instance.SubSun(needSunPoint);
TransitionCooling();
}
3.7 创建第一个植物-向日葵
首先双击背景
随后将中间的摄像头变小一点
随后点开Images中的Plants,再点开SunFLower,就可以看到两种状态的向日葵图层
选中所有的高亮向日葵并拖拽到左边Sense中
先创建一个新的文件夹Animations,并修改文件名为Sunflower_Idle
随后选中新出现的两个文件并放入到Animations中
随后点击上面的Sunflower进行大小修改,这里大小合适,不做修改
随后点击运行,这就就能看到向日葵的动态图
注意:如果这里的向日葵会一闪一闪的,可以点击上面的Sunflower后在右侧的Additional Settings中将Order in Layer的0修改为1
在Scripts中创建一个Plant(用于控制全部植物)的脚本
将它拖入到Sunflower中
3.8 关于植物不同状态的处理
在新建脚本Plant中创建枚举PlantState,里面只有两种状态Disable和Enable
enum PlantState
{
Disable,
Enable
}
在下面编写一个更新方法
private void Update()
{
switch (plantState)
{
case PlantState.Disable:
DisableUpdate();
break;
case PlantState.Enable:
EnableUpdate();
break;
default:
break;
}
}
并编写Disable方法和Enable方法
void DisableUpdate()
{
}
void EnableUpdate()
{
}
标签:随后,僵尸,卡片,状态,void,大战,点击,定时,public
From: https://www.cnblogs.com/czyhyym/p/18498270