操作与总结
参考 Fantasy Skybox FREE 构建自己的游戏场景
游戏场景如上,大部分还是天空盒的功劳,从网上找到素材,然后布局一下就好。
写一个简单的总结,总结游戏对象的使用
常见游戏对象及渲染
使用这些游戏对象构造场景
- 常见游戏对象
- Camera 摄像机
- Skyboxes 天空盒
- 3D 物体显示
- 地形构造工具
- 声音
- 游戏资源库
具体的使用还要看游戏的属性和提供的方法,unity3d给了查看可用资源的功能,所以即使不确定,也可以查看一下,具体的方法比较多,细节也比较多,还是要在实战中积累。
编程实践
牧师与魔鬼 动作分离版
新添加文件
c#文件目录
基本上是按照PPT中的格式写的,在以前的基础上添加了Action文件夹,及里面的6个文件,取代之前move文件的位置,所以move.cs是可以去掉的。
先看添加的6个新文件,因为对这个新模式理解不是很透彻,大概解释参照PPT中的。
CCMoveToAction
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CCMoveToAction : SSAction
{
public Vector3 target;
public float speed;
private CCMoveToAction() { }
public static CCMoveToAction getAction(Vector3 target, float speed)
{
CCMoveToAction action = ScriptableObject.CreateInstance<CCMoveToAction>();
action.target = target;
action.speed = speed;
return action;
}
public override void Update()
{
this.transform.position = Vector3.MoveTowards(this.transform.position, target, speed * Time.deltaTime);
if (this.transform.position == target)
{
this.destroy = true;
this.callback.actionDone(this);
}
}
public override void Start()
{
//
}
}
CCSequenceAction
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CCSequenceAction : SSAction, ISSActionCallback
{
public List<SSAction> sequence;
public int repeat = 1;
public int currentActionIndex = 0;
public static CCSequenceAction getAction(int repeat, int currentActionIndex, List<SSAction> sequence)
{
CCSequenceAction action = ScriptableObject.CreateInstance<CCSequenceAction>();
action.sequence = sequence;
action.repeat = repeat;
action.currentActionIndex = currentActionIndex;
return action;
}
public override void Update()
{
if (sequence.Count == 0) return;
if (currentActionIndex < sequence.Count)
{
sequence[currentActionIndex].Update();
}
}
public void actionDone(SSAction source)
{
source.destroy = false;
this.currentActionIndex++;
if (this.currentActionIndex >= sequence.Count)
{
this.currentActionIndex = 0;
if (repeat > 0) repeat--;
if (repeat == 0)
{
this.destroy = true;
this.callback.actionDone(this);
}
}
}
public override void Start()
{
foreach (SSAction action in sequence)
{
action.gameObject = this.gameObject;
action.transform = this.transform;
action.callback = this;
action.Start();
}
}
void OnDestroy()
{
foreach (SSAction action in sequence)
{
DestroyObject(action);
}
}
}
FirstSceneActionManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FirstSceneActionManager : SSActionManager
{
public void moveBoat(Boat boat)
{
CCMoveToAction action = CCMoveToAction.getAction(boat.getDestination(), boat.movingSpeed);
this.addAction(boat.getGameobj(), action, this);
}
public void moveCharacter(Character characterCtrl, Vector3 destination)
{
Vector3 currentPos = characterCtrl.getPosition();
Vector3 middlePos = currentPos;
if (destination.y > currentPos.y)
{
middlePos.y = destination.y;
}
else
{
middlePos.x = destination.x;
}
SSAction action1 = CCMoveToAction.getAction(middlePos, characterCtrl.movingSpeed);
SSAction action2 = CCMoveToAction.getAction(destination, characterCtrl.movingSpeed);
SSAction seqAction = CCSequenceAction.getAction(1, 0, new List<SSAction> { action1, action2 });
this.addAction(characterCtrl.getGameobj(), seqAction, this);
}
}
这个类可以参照之前的move。
ISSActionCallback
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public interface ISSActionCallback
{
void actionDone(SSAction source);
}
SSAction
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SSAction : ScriptableObject
{
public bool enable = true;
public bool destroy = false;
public GameObject gameObject;
public Transform transform;
public ISSActionCallback callback;
public virtual void Start()
{
throw new System.NotImplementedException();
}
public virtual void Update()
{
throw new System.NotImplementedException();
}
}
SSActionManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SSActionManager : MonoBehaviour, ISSActionCallback
{
private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();
private List<SSAction> waitingToAdd = new List<SSAction>();
private List<int> watingToDelete = new List<int>();
protected void Update()
{
foreach (SSAction ac in waitingToAdd)
{
actions[ac.GetInstanceID()] = ac;
}
waitingToAdd.Clear();
foreach (KeyValuePair<int, SSAction> kv in actions)
{
SSAction ac = kv.Value;
if (ac.destroy)
{
watingToDelete.Add(ac.GetInstanceID());
}
else if (ac.enable)
{
ac.Update();
}
}
foreach (int key in watingToDelete)
{
SSAction ac = actions[key];
actions.Remove(key);
DestroyObject(ac);
}
watingToDelete.Clear();
}
public void addAction(GameObject gameObject, SSAction action, ISSActionCallback whoToNotify)
{
action.gameObject = gameObject;
action.transform = gameObject.transform;
action.callback = whoToNotify;
waitingToAdd.Add(action);
action.Start();
}
public void actionDone(SSAction source)
{
}
}
原文件修改
修改大部分就是把以前涉及到move的代码去掉,举个例子
Character
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Character {
private GameObject character;
public int TypeOfCharacter;//1代表魔鬼,0代表牧师
//private move Cmove;
public int characterStatus;//0代表在岸上,1代表在船上
Coast coast;
Click click;
public float movingSpeed = 20;
public Character(int input)
{
if(input == 0)
{
character = Object.Instantiate(Resources.Load("Perfabs/Priest", typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;
TypeOfCharacter = 0;
}
else
{
character = Object.Instantiate(Resources.Load("Perfabs/Devil", typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;
TypeOfCharacter = 1;
}
//Cmove = character.AddComponent(typeof(move)) as move;
click = character.AddComponent(typeof(Click)) as Click;
click.setGameObj(this);
}
public string getName()
{
return character.name;
}
public void setName(string input)
{
character.name = input;
}
public Vector3 getPosition()
{
return character.transform.position;
}
public void setPosition(Vector3 input)
{
character.transform.position = input;
}
public void getOnBoat(Boat input)
{
character.transform.parent = input.getGameobj().transform;
characterStatus = 1;
}
public void getOnCoast(Coast input)
{
character.transform.parent = null;
characterStatus = 0;
coast = input;
}
public void reset()
{
//Cmove.reset();
coast = (Director.getInstance().currentSceneController as main).RightCoast;
getOnCoast(coast);
setPosition(coast.getEmptyPosition());
coast.getOnCoast(this);
}
/*
public void moveToPosition(Vector3 input)
{
Cmove.setDestination(input);
}*/
public Coast getCoast()
{
return coast;
}
public GameObject getGameobj()
{
return this.character;
}
}
其中注释掉的就是修改的部分,为了后面的main好写,里面新加了一些基本简单的功能。其他的coast以及boat大同小异。
main
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class main : MonoBehaviour,SceneController,ClickAction {
private Coast LeftCoast;
public Coast RightCoast;
private Boat boat;
private Character[] characters;
private Water water;
public simpleGUI simplegui;
private FirstSceneActionManager actionManager;
void Awake()
{
Director director = Director.getInstance();
director.currentSceneController = this;
characters = new Character[6];
loadResources();
simplegui = gameObject.AddComponent<simpleGUI>() as simpleGUI;
actionManager = GetComponent<FirstSceneActionManager>();
}
public void loadResources()
{
LeftCoast = new Coast(-1);
RightCoast = new Coast(1);
boat = new Boat();
//water = new Water();
for (int i = 0; i < 3; i++)
{
Debug.Log("ok");
Character newCharacter = new Character(0);
newCharacter.setName("priest" + i);
newCharacter.setPosition(RightCoast.getEmptyPosition());
newCharacter.getOnCoast(RightCoast);
RightCoast.getOnCoast(newCharacter);
characters[i] = newCharacter;
}
for (int i = 0; i < 3; i++)
{
Character newCharacter = new Character(1);
newCharacter.setName("devil" + i);
newCharacter.setPosition(RightCoast.getEmptyPosition());
newCharacter.getOnCoast(RightCoast);
RightCoast.getOnCoast(newCharacter);
characters[i+3] = newCharacter;
}
}
public void ClickBoat()
{
if (boat.isEmpty())
{
return;
}
else
{
actionManager.moveBoat(boat);
boat.newMove();
}
simplegui.status = gameStatus();
}
public void ClickCharacter(Character input)
{
if (input.characterStatus == 1)//0在岸上,1在船上
{
Coast coast;
Debug.Log(boat.BoatPosStatus);
if (boat.BoatPosStatus == -1)
{
coast = LeftCoast;
}
else
{
coast = RightCoast;
}
boat.GetOffBoat(input.getName());
//input.moveToPosition(coast.getEmptyPosition());
actionManager.moveCharacter(input, coast.getEmptyPosition());
input.getOnCoast(coast);
coast.getOnCoast(input);
}
else
{
Coast coast = input.getCoast();
if (boat.getEmptyIndex() == -1)
{
return;
}
if (coast.TypeOfCoast != boat.BoatPosStatus)
{
return;
}
coast.getOffCoast(input.getName());
actionManager.moveCharacter(input, boat.getEmptyPosition());
input.getOnBoat(boat);
boat.GetOnBoat(input);
}
simplegui.status = gameStatus();
}
public void ClickReset()
{
boat.reset();
LeftCoast.reset();
RightCoast.reset();
for (int i = 0; i < characters.Length; i++)
{
characters[i].reset();
}
}
public int gameStatus()
{
int from_priest = 0;
int from_devil = 0;
int to_priest = 0;
int to_devil = 0;
int[] fromCount = RightCoast.getCharacterNum();
from_priest += fromCount[0];
from_devil += fromCount[1];
int[] toCount = LeftCoast.getCharacterNum();
to_priest += toCount[0];
to_devil += toCount[1];
if (to_priest + to_devil == 6)
return 2;
int[] boatCount = boat.getCharacterNum();
if (boat.BoatPosStatus == -1)
{
to_priest += boatCount[0];
to_devil += boatCount[1];
}
else
{
from_priest += boatCount[0];
from_devil += boatCount[1];
}
if (from_priest < from_devil && from_priest > 0)
{
return 1;
}
if (to_priest < to_devil && to_priest > 0)
{
return 1;
}
return 0;
}
}
main中修改的部分也不算很多,首先是加入变量private FirstSceneActionManager actionManager;
,然后在start里面初始化,loadSource中去掉了water,因为我用了游戏资源库中的贴图,所以直接放在场景中了,也就是说water这个类也可以去掉了。然后下面把move的语句换成用actionManager的语句即可。