在之前三天的代码研究之后,作为之前一直从事UI界面开发,基于公司自己的UI框架。一直都是做着简单的内容,没有从事过核心玩法框架的经验,这次来到新的环境,能够接触到核心玩法对我来说是一种很好的机会。
这是一款以ARkit开发的类似于Pokermon Go的一款单机游戏。主要是钓鱼玩法,钓到宠物通过完成挑战去收服它。
代码框架的核心思路是将游戏的过程分解:从通过ARKit的功能检测平面->钓鱼前的准备工作->抛竿钓鱼->等待鱼上钩->鱼上钩拉竿->收服鱼的挑战过程->挑战结果;而不同的鱼儿挑战过程也有不同的玩法:射击,换装,猜歌,点击...
游戏的思路是通过FishAction这个过程的基类:
using UnityEngine;
using System.Collections;
//抽象触发事件的基础类
namespace GameWorld
{
public enum ActingResult
{
Acting,
Compelet,
UnKnow,
}
public enum FishActionType
{
Exit2Mian,
ARCheck,
FishAimThrow,
FishWait,
FishReady,
FishBite,
FishFailure,
FishChallenge,
FishSuccess,
}
public abstract class FishAction
{
protected GameScene m_GS;
public FishAction(GameScene GameScen)
{
m_GS = GameScen;
}
protected ActingResult m_Result = ActingResult.Compelet;
public ActingResult GetResult
{
get { return m_Result; }
}
public abstract FishActionType ActionType
{
get;
}
public abstract void OnActionEnter();
///
/// 动作进行中
///
public abstract void OnActionExcute();
public abstract void OnActionExit();
}
}
GameScene脚本主要是游戏场景的生成:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using GameWorld;
public class GameScene
{
public TipsCircle TargetCircle;
public GameObject Water;
public GameObject FishAimLine;
public GameObject FishAimTarget;
public GameObject FishRod;
public GameObject StartPos;
public Bait Bait;
public GameObject Fish;
//public GameObject OverTips;
public FishActionManager ActionManager;
public Camera CurCamera;
public GameObject ARSystem;
public GameScene(GameObject water, FishRay fishRay, GameObject fishRod, Bait bait, Camera camera,GameObject ARObject)
{
Debug.Log("GameScene初始化");
ARSystem = ARObject;
CurCamera = camera;
CurCamera.gameObject.SetActive(true);
Water = water;
TargetCircle = water.GetComponent();
//OverTips = TargetCircle.TipsOver;
FishAimLine = fishRay.gameObject;
//fishRay.StartPoint = fishRod.transform.GetChild(0).GetChild(0).transform;
fishRay.CurCamera = CurCamera;
FishAimTarget = fishRay.TargetTips;
FishRod = fishRod;
StartPos = FishAimLine.GetComponent().StartPoint.gameObject;
Bait = bait;
Fish = null;
Init();
}
void Init()
{
ActionManager = new FishActionManager(this);
if (CurCamera.tag=="ARCamera")
ActionManager.ChangeAction(FishActionType.ARCheck);
else if (CurCamera.tag == "NormalCamera")
ActionManager.ChangeAction(FishActionType.FishReady);
}
public virtual void Update ()
{
ActionManager.Update();
}
}
FishActionManager是对游戏流程的管理:
using UnityEngine;
using System.Collections.Generic;
using System;
using GameWorld;
public class FishActionManager : MonoBehaviour
{
private Dictionary m_ActionList;
public FishActionManager(GameScene m_GS)
{
m_ActionList = new Dictionary();
m_ActionList.Add(FishActionType.Exit2Mian, new Exit2Main(m_GS));
m_ActionList.Add(FishActionType.ARCheck, new ARCheck(m_GS));
m_ActionList.Add(FishActionType.FishReady, new FishReady(m_GS));
m_ActionList.Add(FishActionType.FishAimThrow, new FishAimThrow(m_GS));
m_ActionList.Add(FishActionType.FishBite, new FishBite(m_GS));
m_ActionList.Add(FishActionType.FishChallenge, new FishChallenge(m_GS));
m_ActionList.Add(FishActionType.FishWait, new FishWait(m_GS));
m_ActionList.Add(FishActionType.FishFailure, new FishFailure(m_GS));
m_ActionList.Add(FishActionType.FishSuccess, new FishSuccess(m_GS));
}
public void ChangeAction(FishActionType action)
{
CurAction = GetAction(action);
}
private FishAction GetAction(FishActionType action)
{
return m_ActionList.ContainsKey(action) ? m_ActionList[action] : null;
}
private FishAction m_CurAction;
public FishAction CurAction
{
get { return m_CurAction; }
set
{
if (m_CurAction != null)
m_CurAction.OnActionExit();
m_CurAction = value;
if (m_CurAction != null)
m_CurAction.OnActionEnter();
}
}
public void Update()
{
if (m_CurAction != null)
{
m_CurAction.OnActionExcute();
}
}
}
每个流程通过继承自fishAction实现不同的需求再重写父类的方法,通过FishActionManager的ChangeAction方法改变当前流程的状态。
FishChallenge流程中分为很多种玩法,但是玩法总有共通之处,通过FishBase这个玩法基类来实现共同的玩法,子类继承再去各自实现自己私有的玩法,这样方便问题的定位以及游戏的思路更清晰。
FishBase脚本:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using DG.Tweening;
public class FishBase :MonoBehaviour
{
public FishData m_data;
public int Health;
public int CurHealth;
public bool IsDJS;
public float Times;
public UISprite LimitTips;
public UILabel TextTips;
public GameObject NameTips;
public UISprite HealthTips;
public int CurNumber;
public float TogetherTime;
private float MainTime;
public FishManager FishManager;
public FishChallengeState ChallengeState;
private float MoveActionCD;
public string State;
private ProcessFunction PF;
private ProcessFunction PF_01;
private int BIBI;
public bool IsWudi;
private float FistDelayTime=2;
private float IdleTime = 5;
private float CD;
public bool IsAttack;
public bool IsCanAttackNMove;
private AnimatorStateInfo CurAnimaState;
public int BeAttack = 0;
public bool IsDebuffPlayer = false;
public List BulletList = new List();
//-------------------------------------子类继承与覆写
public virtual void Show()
{
FishManager.Tips.GetComponent().BG.mainTexture = FishManager.Tips.GetComponent().Normal;
FishManager.Tips.GetComponent().Text.color = FishManager.Tips.GetComponent().NormalColor;
GameFucntion.DeBug("BaseShow");
if (CurNumber == 1)
{
//GameObject Go = GameFunc.CreatEffect("Eff_Fish_common_Showup");
//Go.transform.SetParent(GameData.CurFishManager.Model.transform);
//Go.transform.localPosition = new Vector3(0, 0, 0);
if (GameData.CurFishConfigData.race >= 4)
{
AudioManagerAT.ins.SetBGMSound("Audio_Bgm_Battleboss");
}
else
{
AudioManagerAT.ins.SetBGMSound("Audio_Bgm_Battlecreature");
}
if (FishManager.Model.GetComponent().ShowUp != null)
{
AudioManagerAT.ins.SetSFXSound(FishManager.Model.GetComponent().ShowUp.name);
}
}
MoveActionCD = 2.5f;
ShowModel(CurNumber);
}
public virtual void UpdateCheck()
{
Idle();
CDing();
MenuBattleMain.ins.m_MenuCtrl.TipsList.UI_Health.UpdateCheck();
GameFunc.NGUI2D_Follow_Model3D(MenuBattleMain.ins.m_MenuCtrl.TipsList.UI_Health.gameObject, GameData.CurFishManager.Model.GetComponentInChildren().HeadTop.gameObject);
}
protected void DJS(int alpha = 1)
{
if (IsDJS)
{
if (FishManager.IsTimeTogether)
{
GameFucntion.DeBug("共同倒计时中");
TogetherTime -= Time.deltaTime;
//Debug.Log("TogetherTime" + TogetherTime);
float a = TogetherTime / MainTime;
//时间进度
//GameData.NGUICamera.GetComponent().LimitTimeTips.TimeGo(a);
MenuBattleMain.ins.m_MenuCtrl.TipsList.UI_LimitTime.TimeGo(a);
//时间显示
MenuBattleMain.ins.m_MenuCtrl.TipsList.UI_LimitTime.LimitTimeText.text = ((int)TogetherTime).ToString();
MenuBattleMain.ins.m_MenuCtrl.TipsList.UI_LimitTime.GetComponent().alpha = alpha;
//GameData.NGUICamera.GetComponent().LimitTimeTips.LimitTimeText.text = ((int)TogetherTime).ToString();
if (TogetherTime <= 0)
{
GameFucntion.DeBug("共同倒计时时间结束");
IsDJS = false;
ChallengeState = FishChallengeState.Run;
}
}
else
{
GameFucntion.DeBug("单独倒计时中");
Times -= Time.deltaTime;
float a = Times / MainTime;
MenuBattleMain.ins.m_MenuCtrl.TipsList.UI_LimitTime.TimeGo(a);
//时间显示
MenuBattleMain.ins.m_MenuCtrl.TipsList.UI_LimitTime.LimitTimeText.text = ((int)Times).ToString();
MenuBattleMain.ins.m_MenuCtrl.TipsList.UI_LimitTime.GetComponent().alpha = alpha;
if (Times <= 0)
{
GameFucntion.DeBug("单独倒计时时间结束");
IsDJS = false;
ChallengeState = FishChallengeState.Run;
}
}
}
}
public virtual void Run()
{
//探头动画
}
public virtual void Get()
{
}
void CDing()
{
if (CD > 0)
{
CD -= Time.deltaTime;
}
else
{
CD = 0;
}
}
void Idle()
{
if (IdleTime < 0)
{
IdleTime = 0;
}
else if (IdleTime > 0)
{
IdleTime -= Time.deltaTime;
}
else if (IdleTime == 0)
{
if (State=="Evolutioning")
{
IdleTime = Random.Range(7, 15);
return;
}
else
{
if (!FishManager.Model.GetComponent())
{
Debug.Log("您还没有添加音效管理脚本");
return;
}
if (FishManager.Model.GetComponent().Idle != null)
{
if (CD != 0)
return;
string temnps = "";
if (m_data.IsEvolution)
{
temnps = "Evo";
}
else
{
AudioManagerAT.ins.SetSFXSound(FishManager.Model.GetComponent().Idle.name);
}
FishManager.Model.transform.GetChild(0).GetComponent().Play("Idle" + temnps + "2");
CD = 3;
}
//}
IdleTime = Random.Range(7, 15);
}
}
}
void ShowTips()
{
Debug.Log("123");
FishManager.Tips.gameObject.SetActive(true);
State = "ShowIntrduce";
//State = "ShowTips";
FishManager.IsCanCheck = true;
}
void ShowModel(int CurNumber)
{
if (CurNumber == 1)
{
AudioManagerAT.ins.SetSFXSound("Audio_fish_Angler@showup_lighting");
GameObject Temp = GameFunc.CreatEffect("Eff_Fish_common_Showup");
Temp.transform.position = GameData.GameSceneData.Water.transform.position;
FishManager.ShowEffect("ShowSky");
FishManager.transform.position = GameData.GameSceneData.Water.transform.position;
FishManager.Model.transform.localPosition = Vector3.zero;
FishManager.Model.transform.GetChild(0).gameObject.SetActive(true);
//鱼单独的音效
if (FishManager.Model.GetComponent())
if (FishManager.Model.GetComponent().ShowUp != null)
AudioManagerAT.ins.SetSFXSound(FishManager.Model.GetComponent().ShowUp.name);
//FishManager.Model.transform.DOLocalJump(new Vector3(0, 1.7f, 0), 1, 1, 1)
// .OnComplete(() =>
// {
// FishManager.ShowEffect("HideSky", GameData.GameSceneData.Water);
// FishManager.Model.GetComponentInChildren().Play(CurNumber + "ShowUp");
// ChallengeState = FishChallengeState.New;
// CheckDJS();
// ShowTips();
// });
ProcessFunction PF05 = new ProcessFunction(0, 0, 1, 0.5f,
(float a) =>
{
float Tempa = (float)(-9 * a * a + 10.7f * a);
FishManager.Model.transform.localPosition = new Vector3(0, Tempa, 0);
},
() =>
{
MenuBattleMain.GetInstance().m_MenuCtrl.TipsList.UI_HitEffect.gameObject.SetActive(true);
ProcessFunction PF = new ProcessFunction(0, 1, 0, 0.25f,
(float a) =>
{
MenuBattleMain.GetInstance().m_MenuCtrl.TipsList.UI_HitEffect.GetComponent().alpha = a;
},
() =>
{
MenuBattleMain.GetInstance().m_MenuCtrl.TipsList.UI_HitEffect.gameObject.SetActive(false);
MenuBattleMain.GetInstance().m_MenuCtrl.TipsList.UI_HitEffect.GetComponent().alpha = 1;
});
//AudioManagerAT.ins.StopSFXZLF("Audio_fish_Angler@showup_lighting");
FishManager.ShowEffect("HideSky");
FishManager.Model.GetComponentInChildren().Play(CurNumber + "ShowUp");
ChallengeState = FishChallengeState.New;
CheckDJS();
ShowTips();
});
}
else
{
FishManager.Model.GetComponentInChildren().Play(CurNumber + "ShowUp");
FishManager.Model.transform.DOLocalMove(new Vector3(0, 1.7f, 0), 1)
.OnComplete(() =>
{
CheckDJS();
ShowTips();
});
}
GameFunc.ARotation2B(GameData.CurFishManager.Model, GameData.WorldCamera.gameObject.transform.position);
MenuBattleMain.GetInstance().m_MenuCtrl.TipsList.WhereEnemy.GetComponent().SetTarget(GameData.WorldCamera.gameObject, FishManager.Model);
MenuBattleMain.GetInstance().m_MenuCtrl.TipsList.WhereEnemy.gameObject.SetActive(true);
MenuBattleMain.GetInstance().m_MenuCtrl.TipsList.WhereEnemy.GetComponent().alpha = 1;
if (FishManager.Model.GetComponentInChildren())
{
FishManager.Model.GetComponentInChildren().Show(CurNumber);
}
}
void CheckDJS()
{
if (FishManager.IsTimeTogether)
{
GameFucntion.DeBug("共同倒计时");
MainTime = FishManager.MainTime;
TogetherTime = FishManager.TogetherTime;
IsDJS = (TogetherTime != 0);
LimitTips.gameObject.SetActive(TogetherTime != 0);
}
else
{
GameFucntion.DeBug("单独倒计时");
MainTime = m_data.LimitTime;
Times = MainTime;
IsDJS = (Times != 0);
LimitTips.gameObject.SetActive(Times != 0);
}
}
public void BossAttack()
{
if (!IsAttack || !IsCanAttackNMove || ChallengeState!=FishChallengeState.New)
return;
IsAttack = false;
if (!FishManager.Model.GetComponent())
FishManager.Model.AddComponent();
FishManager.Model.GetComponent().MoveTarget = FishManager.Model;
FishManager.Model.GetComponent().ColorTarget02 = FishManager.Model.transform.GetChild(0).GetChild(3).gameObject;
FishManager.Model.GetComponent().ColorTarget = FishManager.Model.transform.GetChild(0).GetChild(1).gameObject;
FishManager.Model.GetComponent().Num = 15;
FishManager.Model.GetComponent().Anim = FishManager.Model.transform.GetChild(0).GetComponent();
FishManager.Model.GetComponent().BulletList = BulletList;
FishManager.Model.GetComponent().EnterStart();
}
public void MoveAndAttack(function AttackEvent=null)
{
if (!IsCanAttackNMove )
return;
IsCanAttackNMove = false;
//不走这边的CD,走单独的攻击脚本以复用
if (!FishManager.Model.GetComponent())
FishManager.Model.AddComponent();
FishManager.Model.GetComponent().MoveTarget = FishManager.Model;
FishManager.Model.GetComponent().BulletCount = m_data.BulletCount;
FishManager.Model.GetComponent().ActionMoveType = m_data.MoveType;
FishManager.Model.GetComponent().BulletTarget = FishManager.WorldCamera.transform;
FishManager.Model.GetComponent().BulletShootType = m_data.BulletShootType;
FishManager.Model.GetComponent().Anim = FishManager.Model.GetComponentInChildren();
//FishManager.Model.GetComponent().Anim = FishManager.Model.transform.GetChild(0).GetComponent();
FishManager.Model.GetComponent().BulletNameList = BulletList;
if (m_data.BulletList != null)
{
FishManager.Model.GetComponent().BulletNameList = m_data.BulletList;
//FishManager.Model.GetComponent().BulletNumLimit = new List(m_data.BulletList.Count);
}
FishManager.Model.GetComponent().AttackFramePercent = GameData.CurFishConfigData.AttackFrame;
FishManager.Model.GetComponent().AttackLength = GameData.CurFishConfigData.AttackLength;
if (AttackEvent != null)
FishManager.Model.GetComponent().AttackEvent = AttackEvent;
FishManager.Model.GetComponent().EnterStart();
GameFucntion.DeBug("一次移动和攻击初始化成功");
}
public void ClearMoveAndAttack()
{
if (FishManager.Model.GetComponentInChildren())
FishManager.Model.GetComponent().Clear();
}
public void Evolution()
{
string Temp = "";
if (m_data.IsEvolution)
{
FishManager.ShowEffect("ShowSkyEvo");
FishManager.ShowEffect("AlwaysSky");
FishManager.Model.transform.GetChild(0).GetComponent().Play("Evo");
AudioManagerAT.ins.SetSFXSound("skill_sound_robot_charge");
Temp = "Evo";
}
FishManager.Model.GetComponent().SetBaseMoji("Normal" + Temp);
EyeTips("Active", 1);
State = "Evolutioning";
}
public void ShowTextTips(int Temp=0)
{
//击退+声音+特效
if (Temp % 4 != 0 || FishManager.Tips.GetComponent().alpha > 0 )//|| IsWudi)
{
return;
}
if (m_data.IsOneByOne) //一个字一个字说话
{
if (BIBI == 0)
BIBI = Random.Range(1, m_data.Text.Count);
BIBI++;
int max=0;
if (m_data.IsAttack)//根据攻击判定台词
max = m_data.Text.Count - 1;
else
max = m_data.Text.Count;
if (BIBI >= max)
BIBI = 1;
}
else
{
if (m_data.IsAttack)
BIBI = Random.Range(1, m_data.Text.Count - 1);
else
BIBI = Random.Range(1, m_data.Text.Count);
}
FishManager.Tips.GetComponent().alpha = 1;
MenuBattleMain.ins.m_MenuCtrl.TipsList.UI_TalkText.text = m_data.Text[BIBI];
PF = new ProcessFunction(0, 1, 0, 3,
(float a) =>
{
if (!FishManager.Tips)
return;
FishManager.Tips.GetComponent().alpha = a;
}, null);
}
///
/// 显示眼睛的表情
///
/// 点击次数(如果与点击次数有关的话)
/// 指定表情
/// 持续时间
public void ShowEmotion(int Temp = 0, string str = "",float EndTime=0)
{
if (FishManager.Model.GetComponent().IsActing)
return;
if (Temp % 5 == 0)
{
if (str != null)
if (m_data.IsEvolution)
str += "Evo";
FishManager.Model.GetComponent().ShowEyes(str, EndTime);
}
if (Temp == (int)(m_data.Health * 0.6f))//面部表情改底子
{
string a = "Negative";
if (m_data.IsEvolution)
a += "Evo";
FishManager.Model.GetComponent().SetBaseMoji(a);
}
if (Temp == m_data.Health - 1)//面部表情底子搞回来
{
string a = "Normal";
if (m_data.IsEvolution)
a += "Evo";
FishManager.Model.GetComponent().SetBaseMoji(a);
}
}
///
/// 切换通用moji表情 (可以在循环,内部有CD,也可以单次指定)
///
/// 指定moji表情 1=! 2=纠结 3=?
/// 持续多久
public void ShowEmoji(EmojiType Type, MoveType Action = MoveType.Scale, string str = "", float Time = 1)
{
//Debug.Log("ShowEmoji");
if (FishManager.Emoji.GetComponent().IsActing || CD != 0)
return;
FishManager.Emoji.GetComponent().SetEmoji(Type, str, Action, Time);
#region[Old Moji]
//if (Temp == 0)
//{
// if (str != null)
// FishManager.Emoji.GetComponent().SetTex(str, MoveType.Scale, Time);
//}
//else
//{
// if (Temp != 0 && Temp % 6 == 0)//频率=Temp ; 定制=Str
// {
// if (str != null)
// FishManager.Emoji.GetComponent().SetTex(str, MoveType.Scale, Time);
// else
// FishManager.Emoji.GetComponent().SetTex(a.ToString(), MoveType.Scale, Time * 1.5f);
// }
// else if (Temp != 0 && Temp % 8 == 0)
// FishManager.Emoji.GetComponent().SetTex("2", MoveType.Scale, Time);
//}
#endregion
//对应的情绪的声音
int a = Random.Range(1, 4);
if (FishManager.Model.GetComponent().Angery != null)
{
if (Type == EmojiType.Nagetive || a == 2)
AudioManagerAT.ins.SetSFXSound(FishManager.Model.GetComponent().Angery.name);
}
CD = 3;
}
public void EyeTips(string emoji, float EndTime)
{
string Temp = emoji;
if (m_data.IsEvolution)
Temp += "Evo";
if (!FishManager.Model.GetComponent())
{
Debug.Log("您还没有添加Emotion脚本");
return;
}
FishManager.Model.GetComponent().ShowEyes(Temp, EndTime);
}
}