前言
实验题跟效果跟上次一样,这次只放脚本
github: 纯脚本
一、天空盒构建场景
1. 布置天空
在assets中创建一个material,命名为mySky,将它的Shader改为Skybox/6 Sided,在Fantasy Skybox中找到对应front, back, left, right, up, down六张图导入
其中,可以通过改变Tint Color来改变天空颜色;exposure是来调整天空的曝光度的,可以改变其亮度;rotation不用说了,选择整个天空
这里copy一下学长博客的理解
天空盒是一个全景视图,分为六个纹理,表示沿主轴(上,下,左,右,前,后)可见的六个方向的视图。如果天空盒被正确的生成,纹理图像会在边缘无缝地拼接在一起,可以在内部的任何方向看到周围连续的图像。全景图片会被渲染在场景中的所有其他物体后面,并旋转以匹配相机的当前方向(它不会随着相机的位置而变化,而照相机的位置总是位于全景图的中心)。因此,天空盒子是在图形硬件上以最小负载向场景添加现实性的简单方式。
2.创建地形
选择菜单栏中的GameObject->3D Object->Terrain,建立一块地,然后可以用unity提供的地形设计工具来改变这块地的地形和贴图。
最上面一行是unity提供的简单工具,从左到右依次是:创建相邻地块、绘制地形、种树、种草和设置。
而在绘制地形中又有多种选项,分别是:
升高或降低地形、绘制洞、绘制纹理、设置高度、平滑高度、绘制有特定地质特征的纹理。
一般是左键上升,右键下降。其中Brush Size控制面积,Opacity控制高度
3.完成地形绘制
免费天空盒没有草跟树,这里我就不下载资源,直接随便画了一个地形
二、游戏对象简单总结
在unity中,有很多种游戏对象,包括空对象、3D游戏对象、2D游戏对象、事件、灯光、声音、视频、UI界面、摄像机等。其中我们最常用的就是3D游戏对象、灯光、声音、UI界面和摄像机。
游戏对象是游戏中人物、道具、场景等对象的总称,它们有基础的属性,但没有具体的独特的功能,用于容纳不同的组件。只有挂载了组件后,一个游戏对象才有了属于它的功能。
三、牧师与魔鬼 动作分离版
1.结构图
这里单独把动作拎出来,额外开创了一堆类,用于调整与控制
裁判类
public class Judge : MonoBehaviour//裁判类
{
public int Check(LandModel start_land,LandModel end_land,BoatModel boat)
{
int start_priest = (start_land.GetRoleNum())[0];
int start_devil = (start_land.GetRoleNum())[1];
int end_priest = (end_land.GetRoleNum())[0];
int end_devil = (end_land.GetRoleNum())[1];
if (end_priest + end_devil == 6)return 2; //获胜
int[] boat_role_num = boat.GetRoleNumber();
if (boat.GetBoatSign() == 1) //在开始岸和船上的角色
{
start_priest += boat_role_num[0];
start_devil += boat_role_num[1];
}
else //在结束岸和船上的角色
{
end_priest += boat_role_num[0];
end_devil += boat_role_num[1];
}
if (start_priest > 0 && start_priest < start_devil) //失败
{
return 1;
}
if (end_priest > 0 && end_priest < end_devil) //失败
{
return 1;
}
return 0;
}
}
行动类
由于我在上次作业中已经把行动抽象成一个类,而且三个行动有较大的分割,懒得很难组合成框架,所以我这里只展示框架模板,强行塞进去的行动代码不管。跟上次一样,这些东西都放在model中。
public enum SSActionEventType : int { Started, Complete }
public interface ISSActionCallback {
void SSActionEvent(SSAction source,
SSActionEventType events = SSActionEventType.Complete,
int intParam = 0,
string strParam = null,
Object objectParam = null);
}
public class SSAction : ScriptableObject
{
public bool enable = true;
public bool destroy = false;
public GameObject GameObject { get; set; }
public Transform Transform { get; set; }
public ISSActionCallback Callback { get; set; }
protected SSAction() { }
// Use this for initialization
public virtual void Start()
{
throw new System.NotImplementedException();
}
// Update is called once per frame
public virtual void Update()
{
throw new System.NotImplementedException();
}
}
public class SSMoveToAction : SSAction{
int move_sign = 0; //0是不动,1z轴移动,2x轴移动
float rotaspeed = 200.0f; //转向速度
float mspeed = 5;//移动速度
Transform maincamera;
int kind = 0;//移动方式
Vector3 mid_position;//中间的位置
Vector3 end_position;//最终的位置
Quaternion mid_qua;//移动向中间的朝向
Quaternion end_qua;//移动向最终的朝向
Quaternion final_qua;//站稳后的朝向
Quaternion cameraq;//摄像头的旋转角度
public static SSMoveToAction boatmove( Vector3 position,Transform camera){
SSMoveToAction action = ScriptableObject.CreateInstance<SSMoveToAction>();
action.end_position = position;
action.maincamera = camera;
//摄像头翻转
if(camera.rotation==Quaternion.Euler(0,0,0))action.cameraq = Quaternion.Euler(180,0,180);
else action.cameraq = Quaternion.Euler(0,0,0);
action.kind = 2;
action.move_sign=1;
action.rotaspeed = 200;
action.mspeed = 2;
return action;
}
// -90前 0右 90后 180左
public static SSMoveToAction movetoland(GameObject role,LandModel land){
SSMoveToAction action = ScriptableObject.CreateInstance<SSMoveToAction>();
Vector3 position = land.GetEmptyPosition();
action.mid_position = new Vector3(position.x,role.transform.position.y,role.transform.position.z);
action.end_position = new Vector3(position.x,role.transform.position.y,position.z);
if(land.GetLandSign() == 1){//走下初始大陆上的转向方式
action.mid_qua = Quaternion.Euler(0,90,0);
if(position.z>role.transform.position.z)action.end_qua= Quaternion.Euler(0,0,0);
else action.end_qua = Quaternion.Euler(0,180,0);
action.final_qua = Quaternion.Euler(0,-90,0);
}
else{//走下对面大陆上的转向方式
action.mid_qua = Quaternion.Euler(0,-90,0);
if(position.z>role.transform.position.z)action.end_qua= Quaternion.Euler(0,0,0);
else action.end_qua = Quaternion.Euler(0,180,0);
action.final_qua = Quaternion.Euler(0,90,0);
}
action.kind = 1;
action.move_sign = 1;
return action;
}
public static SSMoveToAction movetoboat(GameObject role,BoatModel boat){
SSMoveToAction action = ScriptableObject.CreateInstance<SSMoveToAction>();
Vector3 position = boat.GetEmptyPosition();
action.mid_position = new Vector3(role.transform.position.x,role.transform.position.y,position.z);
action.end_position = new Vector3(position.x,role.transform.position.y,position.z);
if(boat.GetBoatSign() == 1){//船在初始大陆上的转向方式
if(position.z>role.transform.position.z)action.mid_qua = Quaternion.Euler(0,0,0);
else action.mid_qua = Quaternion.Euler(0,180,0);
action.end_qua = action.final_qua = Quaternion.Euler(0,-90,0);
}
else{//船在对面大陆上的转向方式
if(position.z>role.transform.position.z)action.mid_qua = Quaternion.Euler(0,0,0);
else action.mid_qua = Quaternion.Euler(0,180,0);
action.end_qua = action.final_qua = Quaternion.Euler(0,90,0);
}
action.kind = 1;
action.move_sign = 1;
return action;
}
public int getmovesign(){
return move_sign;
}
public override void Start(){
}
public override void Update()
{
if(kind == 1)roleUpdate();
else if(kind == 2) boatUpdate();
if(move_sign == 0)
{
this.destroy = true;
// 完成动作后进行动作回掉
this.Callback.SSActionEvent(this);
}
}
void boatUpdate(){
if(move_sign==1){
//渐慢的镜头旋转
maincamera.rotation = Quaternion.RotateTowards(maincamera.rotation, cameraq, rotaspeed*Time.deltaTime);
if(rotaspeed>0)rotaspeed -= 120*Time.deltaTime>rotaspeed?rotaspeed: 120*Time.deltaTime;
this.Transform.position = Vector3.MoveTowards(this.Transform.position, end_position,mspeed * Time.deltaTime);
if(this.Transform.position==end_position)move_sign=0;
}
}
void roleUpdate(){
if(move_sign == 1){// 移动前转向
this.Transform.rotation = Quaternion.RotateTowards(this.Transform.rotation, mid_qua, rotaspeed*Time.deltaTime);
if(this.Transform.rotation==mid_qua)move_sign=2;
}
else if(move_sign == 2){//移动到中间
this.Transform.position = Vector3.MoveTowards(this.Transform.position, mid_position, mspeed * Time.deltaTime);
if (this.Transform.position == mid_position)move_sign=3;
}
else if(move_sign == 3){//在中间转向
this.Transform.rotation = Quaternion.RotateTowards(this.Transform.rotation, end_qua, rotaspeed*Time.deltaTime);
if(this.Transform.rotation==end_qua)move_sign=4;
}
else if(move_sign == 4){//移动到最终目的地
this.Transform.position = Vector3.MoveTowards(this.Transform.position, end_position, mspeed * Time.deltaTime);
if (this.Transform.position == end_position)move_sign=5;
}
else if(move_sign == 5){//在最终目的地转向
this.Transform.rotation = Quaternion.RotateTowards(this.Transform.rotation, final_qua, rotaspeed*Time.deltaTime);
if(this.Transform.rotation==final_qua)move_sign=0;
}
}
public int moves(){
return move_sign;
}
}
public class SSSequenceAction : SSAction, ISSActionCallback{
public List<SSAction> sequence;
public int repeat = -1;
public int start = 0;
// 创建并返回动作序列的实例
public static SSSequenceAction GetSSSequenceAction(int repeat, int start, List<SSAction> sequence){
SSSequenceAction action = ScriptableObject.CreateInstance<SSSequenceAction>();
action.repeat = repeat;
action.sequence = sequence;
action.start = start;
return action;
}
// 在 Update 中执行当前动作
public override void Update(){
if (sequence.Count == 0) return;
if (start < sequence.Count)
{
sequence[start].Update();
}
}
// 更新当前执行的动作
public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Complete,
int intParam = 0, string strParam = null, Object objectParam = null) {
source.destroy = false;
this.start++;
if (this.start >= sequence.Count)
{
this.start = 0;
if (repeat > 0) repeat--;
if (repeat == 0)
{
this.destroy = true;
this.Callback.SSActionEvent(this);
}
}
}
// Use this for initialization
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)
{
Destroy(action);
}
}
}
public class SSActionManager : MonoBehaviour{
private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();
private List<SSAction> waitingAdd = new List<SSAction>();
private List<int> waitingDelete = new List<int>();
protected void Update(){
foreach (SSAction action in waitingAdd){
actions[action.GetInstanceID()] = action;
}
waitingAdd.Clear();
foreach (KeyValuePair<int, SSAction> KeyValue in actions){
SSAction action = KeyValue.Value;
if (action.destroy){
waitingDelete.Add(action.GetInstanceID()); // release action
}
else if (action.enable){
action.Update(); // update action
}
}
foreach (int key in waitingDelete){
SSAction action = actions[key];
actions.Remove(key);
Destroy(action);
}
waitingDelete.Clear();
}
protected void Start(){
}
// 执行动作
public void RunAction(GameObject gameObject,SSAction action, ISSActionCallback callback){
action.GameObject = gameObject;
action.Transform = gameObject.transform;
action.Callback = callback;
waitingAdd.Add(action);
action.Start();
}
public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Complete,
int intParam = 0, string strParam = null, Object objectParam = null){
}
}
public class ActionManager : SSActionManager, ISSActionCallback
{
private SSMoveToAction boat_move;
private SSMoveToAction char_move;
public ISceneController sceneController;
protected new void Start()
{
sceneController = (ISceneController)SSDirector.GetInstance().CurrentScenceController;
char_move =boat_move = ScriptableObject.CreateInstance<SSMoveToAction>();
}
public void moveBoat(GameObject boat,Vector3 dest, Transform maincamera)
{
boat_move = SSMoveToAction.boatmove(dest,maincamera);
this.RunAction(boat, boat_move, this);
}
public void movetoland(GameObject role,LandModel land){
char_move = SSMoveToAction.movetoland(role,land);
this.RunAction(role,char_move,this);
}
public void movetoboat(GameObject role,BoatModel boat){
char_move = SSMoveToAction.movetoboat(role,boat);
this.RunAction(role,char_move,this);
}
public int getboatmovesign(){
return boat_move.moves();
}
public int getrolemovesign(){
return char_move.moves();
}
}