导入素材创建场景
游戏开始场景制作
星星闪耀动画的制作
特效孵化器
添加一个EffectSpawn脚本,用来泼撒花瓣和爱心
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 特效孵化器
/// </summary>
public class EffectSpawn : MonoBehaviour {public GameObject[] effectGos;public Transform canvasTrans;// Use this for initializationvoid Start () {}// Update is called once per framevoid Update () {}private void CreateEffectGo(){int randomIndex = Random.Range(0, 2);GameObject effectGo = Instantiate(effectGos[randomIndex], transform.position, transform.rotation);effectGo.transform.SetParent(canvasTrans);}
}
在屏幕右上角创建空物体,将脚本挂载在它上面,并添加预制体
特效的移动脚本
在EffectSpawn脚本的Start力添加以下代码,让花瓣和爱心两秒随机生成一次
InvokeRepeating("CreateEffectGo", 0, 2);
在花瓣和爱心预制体上创建新的脚本EffectMove,用来控制物体的移动
using System.Collections;
using System.Collections.Generic;
using UnityEngine;/// <summary>
/// 特效移动
/// </summary>
public class EffectMove : MonoBehaviour {public float moveSpeed = 5;// Use this for initializationvoid Start () {Destroy(gameObject, 10);}// Update is called once per framevoid Update () {transform.Translate(-transform.right * moveSpeed * Time.deltaTime);}
}
特效的完善
首先在EffectSpawn里修改孵化器的角度为45度
transform.rotation = Quaternion.Euler(new Vector3(0, 0, Random.Range(0, 45)));
然后在EffectMove里添加复合运动的代码,让特效看起来更真实
private float timeVal;private int randomYPos;void Update () {transform.Translate(-transform.right * moveSpeed * Time.deltaTime);if(timeVal >= 1){timeVal = 0;randomYPos = Random.Range(-1, 2);}else{transform.Translate(transform.up * randomYPos * Time.deltaTime * moveSpeed / 5);timeVal += Time.deltaTime;}}
添加音乐,然后给Buttont添加加载Game场景的代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;/// <summary>
/// 开始按钮的功能
/// </summary>
public class LoadGame : MonoBehaviour
{public void OnButtonStartClick(){SceneManager.LoadScene(1);}}
点击Start就加载到Game场景
搭建游戏场景导入Live2d框架
使用框架来加载Live2d模型
输入模型Json文件的地址就可以显示出来模型
完成金币显示的UI
游戏场景UI的制作
游戏管理的创建
创建GameManager脚本用来管理金币、好感度和日期。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class GameManager : MonoBehaviour
{//单例private static GameManager _instance;public static GameManager Instance{get{return _instance;}}//玩家属性public int gold;public int favor;public int leftDays;public Text goldText;public Text favorTest;public Text dateText;private void Awake(){_instance = this;gold = favor = 0;leftDays = 20;}// Update is called once per framevoid Update(){}
}
更新文本UI的方法
在GamaManger里面添加更新UI的方法
//更新玩家属性UI显示private void UpdateUI(){goldText.text = gold.ToString();favorTest.text = favor.ToString();dateText.text = leftDays.ToString();}//金币数额的变化方法public void ChangeGold(int goldValue){gold += goldValue;if (gold <= 0)gold = 0;UpdateUI();}//好感度数额的变化方法public void ChangeFavor(int favorValue){favor += favorValue;if (favor <= 0)favor = 0;UpdateUI();}
天亮天黑方法
首先添加三个状态来控制天亮天黑
//天黑天亮属性public Image mask;private bool toAnotherDay;private bool toBeDay;
添加天亮天黑的方法
//天黑public void ToDark(){mask.color += new Color(0, 0, 0, Mathf.Lerp(0, 1, 0.1f));if(mask.color.a >= 0.8f){mask.color = new Color(0, 0, 0, 1);toBeDay = true;UpdateUI();}}//天亮public void ToDay(){mask.color -= new Color(0, 0, 0, Mathf.Lerp(1, 0, 0.1f));if (mask.color.a <= 0.2f){mask.color = new Color(0, 0, 0, 0);toAnotherDay = false;toBeDay = false;}}
天黑天亮方法的具体运行与打工按钮的制作
完善天亮天黑的办法
//天黑天亮属性public Image mask;public bool toAnotherDay;public bool toBeDay;private float timeVal;
void Update(){//是否过渡到另外一天if (toAnotherDay){if (toBeDay){//天亮if (timeVal >= 2){ToDay();timeVal = 0;}else{timeVal += Time.deltaTime;}}else{//天黑ToDark();}}}
添加打工的分类
打工与对话框UI的制作
打工按钮事件的处理
public GameObject actionBtns;//工作public GameObject workBtns;
添加方法ClickWorkBtn()
public void ClickWorkBtn(){actionBtns.SetActive(false);workBtns.SetActive(true);}
打工后获取金币的方法
首先添加几个属性
public LAppModelProxy lAppModelProxy;public GameObject talkLine;public Text talkLineText;//工作public GameObject workBtns;public Sprite[] workSprites;public Image workImage;public GameObject workUI;
添加点击工作以及赚钱的代码
public void ClickWorkBtn(){actionBtns.SetActive(false);workBtns.SetActive(true);lAppModelProxy.SetVisible(false);//隐藏模型}public void GetMoney(int workIndex){workBtns.SetActive(false);ChangeGold((4 - workIndex) * 20);workImage.sprite = workSprites[workIndex];workUI.SetActive(true);talkLine.SetActive(true);talkLineText.text = "劳动最光荣";}
打工流程的测试
添加一个即将天黑的代码,用来点击控制toAnotherDya
//即将天黑public void ToBeDark(){toAnotherDay = true;}
给各种属性进行赋值
进行测试
重置所有UI显示的方法
添加重置UI显示的办法
//重置所有UIprivate void ResetUI(){workUI.SetActive(false);talkLine.SetActive(false);actionBtns.SetActive(true);lAppModelProxy.SetVisible(true);leftDays--;UpdateUI();}
并在天黑的代码里进行调用
//天黑public void ToDark(){mask.color += new Color(0, 0, 0, Mathf.Lerp(0, 1, 0.1f));if(mask.color.a >= 0.8f){mask.color = new Color(0, 0, 0, 1);toBeDay = true;UpdateUI();ResetUI();}}
聊天UI的制作
聊天按钮的事件
添加聊天的属性
//聊天public GameObject chatUI;
添加聊天按钮的事件
//聊天public void ClickChatBtn(){actionBtns.SetActive(false);chatUI.SetActive(true);}
使用框架的方法播放动作
根据好感度不同播放不同的动画
//聊天public void ClickChatBtn(){actionBtns.SetActive(false);chatUI.SetActive(true);if(favor >= 100){lAppModelProxy.GetModel().StartMotion("tap_body", 1, 2);}else{lAppModelProxy.GetModel().StartMotion("tap_body", 0, 2);}}
使用框架的方法设置表情
public void GetFavor(int chatIndex){chatUI.SetActive(false);talkLine.SetActive(true);switch (chatIndex){case 0:if (favor > 20){ChangeFavor(10);talkLineText.text = "谢谢啊,二狗子,你也很帅。。。";}else{ChangeFavor(2);talkLineText.text = "哦,谢谢。";lAppModelProxy.GetModel().SetExpression("f08");}break;case 1:if (favor > 60){ChangeFavor(20);talkLineText.text = "啊。。哦,不好意思,谢谢哈。。。";lAppModelProxy.GetModel().SetExpression("f07");}else{ChangeFavor(2);talkLineText.text = "哦,谢谢。";lAppModelProxy.GetModel().SetExpression("f08");}break;default:break;}}
聊天功能的完善
public void GetFavor(int chatIndex){chatUI.SetActive(false);talkLine.SetActive(true);switch (chatIndex){case 0:if (favor > 20){ChangeFavor(10);talkLineText.text = "谢谢啊,二狗子,你也很帅。。。";}else{ChangeFavor(2);talkLineText.text = "哦,谢谢。";lAppModelProxy.GetModel().SetExpression("f08");}break;case 1:if (favor > 60){ChangeFavor(20);talkLineText.text = "啊。。哦,不好意思,谢谢哈。。。";lAppModelProxy.GetModel().SetExpression("f07");}else{ChangeFavor(-20);talkLineText.text = "你看错了!你手拿开,真不礼貌。";lAppModelProxy.GetModel().SetExpression("f03");}break;case 2:if (favor > 100){ChangeFavor(40);talkLineText.text = "那。。咱们一起去吃饭,下午去哪玩?";lAppModelProxy.GetModel().SetExpression("f05");}else{ChangeFavor(-40);talkLineText.text = "你这人说话怎么这样啊,我又没得罪你。";lAppModelProxy.GetModel().SetExpression("f04");}break;default:break;}
解决文本因自动适应而字体过小的方法
在代码里面添加"\n"换行即可。
在ResetUI里添加表情重置。
lAppModelProxy.GetModel().SetExpression("f01");
学校门口约会的情况
首先定义个两个约会使用到的变量
//约会public SpriteRenderer bgImage;public Sprite[] dateSprites;
然后开始写约会的方法
/// <summary>/// 约会/// </summary>public void ClickDataBtn(){actionBtns.SetActive(false);talkLine.SetActive(true);int randomNum = Random.Range(1, 4);bool hasEnoughGold = false;bgImage.sprite = dateSprites[randomNum];switch(randomNum){case 1:if(gold >= 50){ChangeGold(-50);ChangeFavor(150);talkLineText.text = "学校门口原来有这么好玩的地方。" + "\n" +"今天谢谢你了,二狗子。";hasEnoughGold = true;}else{talkLineText.text = "没事,不用在意,我最近零花钱比较多。";ChangeGold(-50);}break;default:break;}}
约会方法的完善
/// <summary>/// 约会/// </summary>public void ClickDataBtn(){actionBtns.SetActive(false);talkLine.SetActive(true);int randomNum = Random.Range(1, 4);bool hasEnoughGold = false;bgImage.sprite = dateSprites[randomNum];switch(randomNum){case 1:if(gold >= 50){ChangeGold(-50);ChangeFavor(150);talkLineText.text = "学校门口原来有这么好玩的地方。" + "\n" +"今天谢谢你了,二狗子。";hasEnoughGold = true;}else{talkLineText.text = "没事,不用在意,我最近零花钱比较多。";ChangeGold(-50);}break;case 2:if (gold >= 150){ChangeGold(-150);ChangeFavor(300);talkLineText.text = "蟹黄汤包,烤鸭还有其他的甜品真的都太好吃了!" + "\n" +"谢谢招待!";hasEnoughGold = true;}else{talkLineText.text = "下次有机会你再请我吃饭吧。";ChangeFavor(-150);}break;case 3:if (gold >= 300){ChangeGold(-300);ChangeFavor(500);talkLineText.text = "今天真的很开心," + "\n" +"还有,谢谢你送的礼物,你人真好。。。";hasEnoughGold = true;}else{talkLineText.text = "那个娃娃真的好可爱哦,好想要。。。";ChangeFavor(-300);}break;default:break;}if (hasEnoughGold){lAppModelProxy.GetModel().StartMotion("pinch_in", 0, 2);}else{lAppModelProxy.GetModel().StartMotion("flick_head", 0, 2);}}
表白方法的编写
/// <summary>/// 表白/// </summary>public void ClickLoveBtn(){actionBtns.SetActive(false);talkLine.SetActive(true);if(favor >= 1500){//表白成功talkLineText.text = "谢谢你啊,二狗子。其实我也喜欢你很久了," + "/n" +"自己喜欢的那个人也正好喜欢着自己," + "\n" +"真好,希望你可以让我永远陪着你。";lAppModelProxy.GetModel().StartMotion("pinch_out", 0, 2);}
表白功能的测试
完善表白功能的代码
/// <summary>/// 表白/// </summary>public void ClickLoveBtn(){actionBtns.SetActive(false);talkLine.SetActive(true);if(favor >= 1500){//表白成功talkLineText.text = "谢谢你啊,二狗子。其实我也喜欢你很久了," + "/n" +"自己喜欢的那个人也正好喜欢着自己," + "\n" +"真好,希望你可以让我永远陪着你。";lAppModelProxy.GetModel().StartMotion("pinch_out", 0, 2);lAppModelProxy.GetModel().SetExpression("f07");}else{//表白失败talkLineText.text = "二狗子,你。。你," + "\n" +"突然的表白的吓我一跳" + "\n" +"你真的喜欢我是吗?" + "\n" +"可是。。。我们还不够了解彼此。。。";lAppModelProxy.GetModel().StartMotion("shake", 0, 2);lAppModelProxy.GetModel().SetExpression("f04");}}
野生Live2d模型素材文件的处理与BOSS脚本的创建
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Live2DSimpleModel : MonoBehaviour
{public TextAsset modelFile;public Texture2D texture;public TextAsset idleMotionFile;public GameObject manatsu;// Start is called before the first frame updatevoid Start(){}// Update is called once per framevoid Update(){}
}
Boss脚本的成员变量的定义与Start方法的编写
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using live2d;public class Live2DSimpleModel : MonoBehaviour
{public TextAsset modelFile;public Texture2D texture;public TextAsset idleMotionFile;public GameObject manatsu;private Live2DModelUnity live2DModel;private Matrix4x4 live2DCanvasPos;private Live2DMotion live2DMotionIdle;private MotionQueueManager motionQueueManager;private EyeBlinkMotion eyeBlinkMotion;// Start is called before the first frame updatevoid Start(){Live2D.init();live2DModel = Live2DModelUnity.loadModel(modelFile.bytes);live2DModel.setTexture(0, texture);float modelWidth = live2DModel.getCanvasWidth();live2DCanvasPos = Matrix4x4.Ortho(0, modelWidth, modelWidth, 0, -50.0f, 50.0f);live2DMotionIdle = Live2DMotion.loadMotion(idleMotionFile.bytes);live2DMotionIdle.setLoop(true);motionQueueManager = new MotionQueueManager();eyeBlinkMotion = new EyeBlinkMotion();motionQueueManager.startMotion(live2DMotionIdle);}// Update is called once per framevoid Update(){}
}
Boss渲染的完成与位置和比例的设置
完善Boss的代码
// Update is called once per framevoid Update(){live2DModel.setMatrix(transform.localToWorldMatrix * live2DCanvasPos);motionQueueManager.updateParam(live2DModel);eyeBlinkMotion.setParam(live2DModel);live2DModel.update();}private void OnRenderObject(){live2DModel.draw();}
Boss移动方法的编写
首先创建几个变量
public float moveSpeed;private Vector3 initPos;//判断当前Boss是否被打败private bool isDefeat;
initPos = transform.position;
然后在Update里面添加Boss移动的方法
if (GameManager.Instance.gameOver){return;}//判断当前Boss是否追赶上Manatsuif (manatsu.transform.position.x - transform.position.x < 3){GameManager.Instance.gameOver = true;}if (isDefeat){transform.position = Vector3.Lerp(transform.position, initPos, 0.2f);}else{transform.Translate(Vector3.right * moveSpeed * Time.deltaTime);}
击打Boss的方法
创建一个计数变量,用来记录打击次数
private int hitCount;
private void OnMouseDown(){if (GameManager.Instance.gameOver){return;}if (hitCount >= 20){isDefeat = true;}else{hitCount++;}}
在Manatsu身上的脚本添加下列属性,以便Manatsu淘宝
public bool isRunningAway;public float moveSpeed;
Manatsu的逃跑方法
首先在GameManager中添加一个属性,用来控制BadBoy
public Live2DSimpleModel badBoyScript;
在Manatsu身上的脚本中添加逃跑方法,首要记录初始位置
initPos = transform.position;
然后在Update里添加逃跑方法
if(GameManager.Instance != null){if (GameManager.Instance.gameOver){isRunningAway = false;return;}}if (isRunningAway){transform.Translate(Vector3.right * moveSpeed * Time.deltaTime);}if (GameManager.Instance != null){if (GameManager.Instance.badBoyScript.isDefeat){transform.position = Vector3.Lerp(transform.position, initPos, 0.1f);}}
Boss的有关逻辑处理
在GameManager中添加一个对话框
public GameObject badBoyTalkLine;
然后添加一个产生坏男孩和关闭对话框的方法
//产生坏男孩private void CreateBadBoy(){lAppModelProxy.isRunningAway = true;badBoyScript.gameObject.SetActive(true);lAppModelProxy.GetModel().SetExpression("f04");actionBtns.SetActive(false);badBoyTalkLine.SetActive(true);}public void CloseBadBoyTalkLine(){badBoyTalkLine.SetActive(false);}
然后在ResetUI里面进行调用
//重置所有UIprivate void ResetUI(){workUI.SetActive(false);talkLine.SetActive(false);actionBtns.SetActive(true);lAppModelProxy.SetVisible(true);leftDays--;lAppModelProxy.GetModel().SetExpression("f01");bgImage.sprite = dateSprites[0];UpdateUI();if(leftDays == 5){CreateBadBoy();}}
击败Boss之后的文本提示与处理
public void DefeatBadBoy(){lAppModelProxy.GetModel().StartMotion("shake", 0, 2);talkLine.SetActive(true);talkLineText.text = "刚才吓死我了,谢谢你,二狗子" + "\n" +"要不是你及时救我,我就。。。" + "\n" +"你人好勇敢,真帅。。。";ChangeFavor(300);}
然后在Boss的脚本里进行调用
if (hitCount >= 20){isDefeat = true;GameManager.Instance.DefeatBadBoy();}
鼠标点击特效的动画制作
鼠标点击时产生特效的代码实现
首先添加两个变量,一个是预制体,一个是Canvas
//其他public GameObject clickEffect;public Canvas canvas;
在Update里添加产生特效的代码
//产生鼠标点击特效if (Input.GetMouseButtonDown(0)){Vector2 mousePos = Vector2.one;RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform, Input.mousePosition, canvas.worldCamera, out mousePos);GameObject go = Instantiate(clickEffect);go.transform.SetParent(canvas.transform);go.transform.localPosition = mousePos;}
游戏结束UI的制作
public GameObject gameOverBtns;
然后在Update里面进行判断
//游戏结束逻辑if (gameOver){talkLine.SetActive(true);gameOverBtns.SetActive(true);actionBtns.SetActive(false);}
游戏结束逻辑的编写
//游戏结束逻辑if (gameOver){talkLine.SetActive(true);gameOverBtns.SetActive(true);actionBtns.SetActive(false);if (favor >= 1500){talkLineText.text = "二狗子终于追到了乃木坂最腹黑的钓师——Manatsu。" + "\n" +"最后他们幸福的在一起了!";}else if(leftDays!=0&&favor < 1500){talkLineText.text = "Manatsu受到欺负时二狗子没有保护她," + "\n" +"从此他们决裂了。";}else{talkLineText.text = "二狗子在出国前没能获取到Manatsu的芳心," + "\n" +"于是他们没能在一起。";}}
添加按钮加载场景的代码
public void LoadScene(int sceneNum){SceneManager.LoadScene(sceneNum);}
给女主角换衣服
首先创建一个用来存储衣服的变量
public Texture2D manatusNewCloth;
然后在ResetUI里面进行使用
else if (leftDays == 10){Live2DModelUnity live2DModelUnity = lAppModelProxy.GetModel().GetLive2DModelUnity();live2DModelUnity.setTexture(2, manatusNewCloth);}
贴图混乱的原因与衣服制作的简单说明
必须要保证新服装的贴图和以前的贴图位置相同,这样才能避免贴图混乱。
按钮音乐播放方法的封装与音乐资源的赋值
//音乐播放private AudioSource audioSource;public AudioClip[] audioClips;
首先在Awake中进行初始化
audioSource = GetComponent<AudioSource>();audioSource.loop = true;audioSource.clip = audioClips[0];audioSource.Play();
添加Button点击的音效
public void PlayButtonSound(){audioSource.PlayOneShot(audioClips[8]);}
音乐添加的完成
完成音乐的添加。