游戏对象与图形基础(中山大学3d游戏第4次作业)

游戏对象与图形基础(中山大学3d游戏第4次作业)


仓库地址:https://github.com/linfn3/3dunity/tree/main/devils_and_priests_2
视频地址:https://www.bilibili.com/video/BV1mm4y1w7xy/
备注:考虑到每次上传速度,后面每次仓库只上传assert文件!

一、天空盒

assertstore中下载资源
在这里插入图片描述
导入资源:
在这里插入图片描述
天空盒设置:
在这里插入图片描述
效果:
在这里插入图片描述

二、游戏对象总结

GameObject是所有组件 Component 的容器。游戏中所有的对象都可认为是游戏对象(GameObject)。它可以被制作成预制反复使用。它拥有众多属性,例如材质、Transform,它可以被实例化,并且通过c#脚本控制。

三、牧师与魔鬼 动作分离版

1.首先在interface中添加新的接口

我们需要添加接口ActionCallback,代码如下:

    public interface ActionCallback
    {
        void ActionDone(SSAction source);
    }

2.ActionController文件

我们需要编写动作基类SSAction,移动类Moveaction和组合类ConstituteAction(实现ActionCallback接口,主要完成上下船操作)以及管理类ActionManager(实现ActionCallback接口,用于管理和整合动作)
代码如下:

using System.Collections.Generic;
using UnityEngine;
using MyNamespace;


public class SSAction : ScriptableObject
{ 
    public bool enable = true; 
    public bool destroy = false; 
    public GameObject GameObject { get; set; }
    public Transform Transform { get; set; }
    public ActionCallback Callback { get; set; }

    public virtual void Start()
    {
        throw new System.NotImplementedException();
    }

    public virtual void Update()
    {
        throw new System.NotImplementedException();
    }
}


public class Moveaction : SSAction
{

    public Vector3 target;
    public float speed;

    private Moveaction() { }

    public static Moveaction GetSSMoveToAction(Vector3 goal, float speed)
    {
        Moveaction action = CreateInstance<Moveaction>();
        action.target = goal;
        action.speed = speed;
        return action;
    }
    public override void Start() { }


    public override void Update()
    {
        Transform.position = Vector3.MoveTowards(Transform.position, target, speed * Time.deltaTime);
        if (Transform.position == target)
        {
            destroy = true;
            Callback.ActionDone(this);
        }
    }
}

public class ConstituteAction : SSAction, ActionCallback
{
    public int tmp = -1;
    public int ActionIndex = 0;
    public List<SSAction> sequence;

    public static ConstituteAction GetConstitueAction(int repeat, int currentActionIndex, List<SSAction> sequence)
    {
        ConstituteAction action = CreateInstance<ConstituteAction>();
        action.sequence = sequence;
        action.tmp = repeat;
        action.ActionIndex = currentActionIndex;
        return action;
    }
    public override void Update()
    {
        if (sequence.Count == 0) return;
        if (ActionIndex < sequence.Count)
        {
            sequence[ActionIndex].Update();
        }
    }


    public override void Start()
    {
        foreach (SSAction action in sequence)
        {
            action.GameObject = GameObject;
            action.Transform = Transform;
            action.Callback = this;
            action.Start();
        }
    }
    void OnDestroy()
    {
        foreach (SSAction action in sequence)
        {
            Destroy(action);
        }
    }

    public void ActionDone(SSAction source)
    {
        source.destroy = false;
        ActionIndex++;
        if (ActionIndex >= sequence.Count)
        {
            ActionIndex = 0;
            if (tmp > 0) tmp--;
            if (tmp == 0)
            {
                destroy = true;
                Callback.ActionDone(this);
            }
        }
    }
}

public class ActionManager : MonoBehaviour, ActionCallback
{
    private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();

    private List<int> deletelist = new List<int>();
    private List<SSAction> addlist = new List<SSAction>();

    protected void Update()
    {
        foreach (SSAction action in addlist)
        {
            actions[action.GetInstanceID()] = action;
        }
        addlist.Clear();

        foreach (KeyValuePair<int, SSAction> kv in actions)
        {
            SSAction action = kv.Value;
            if (action.destroy)
            {
                deletelist.Add(action.GetInstanceID());
            }
            else if (action.enable)
            {
                action.Update();
            }
        }

        foreach (int key in deletelist)
        {
            SSAction action = actions[key];
            actions.Remove(key);
            Destroy(action);
        }
        deletelist.Clear();
    }

    public void AddAction(GameObject gameObject, SSAction action, ActionCallback callback)
    {
        action.Transform = gameObject.transform;
        action.Callback = callback;
        action.GameObject = gameObject;
        addlist.Add(action);
        action.Start();
    }

    public void ActionDone(SSAction source) { }
}

3. 移除Moveable类

因为已经有了动作管理类ActionController,就不再需要移动控制类Moveable了。

4. 编写SceneController

这是一个场景控制类,用于控制船、恶魔、牧师的运动

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using MyNamespace;

public class SceneController : ActionManager
{
    public void MoveBoat(BoatController boatController)
    {
        Moveaction action = Moveaction.GetSSMoveToAction(boatController.GetDestination(), boatController.boat.movingSpeed);
        AddAction(boatController.boat.boatObject, action, this);
    }

    public void MoveCharacter(MyNamespace.CharacterController characterController, Vector3 destination)
    {
        Vector3 curpos = characterController.character.Role.transform.position;
        Vector3 midpos = curpos;

        if (curpos.y < destination.y  ) midpos.y = destination.y;
        else
        {
            midpos.x = destination.x;
        }
        SSAction action1 = Moveaction.GetSSMoveToAction(midpos, characterController.character.movingSpeed);
        SSAction action2 = Moveaction.GetSSMoveToAction(destination, characterController.character.movingSpeed);
        SSAction seqAction = ConstituteAction.GetConstitueAction(1, 0, new List<SSAction> { action1, action2 });
        AddAction(characterController.character.Role, seqAction, this);
    }
}

5. 编写裁判类check.cs

这个类用于判断游戏是否结束及输赢,游戏胜利返回2,游戏失败返回1,游戏未结束返回0.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace MyNamespace
{
    public class Check : MonoBehaviour
    {
        public FirstController sceneController;

        protected void Start()
        {
            sceneController = (FirstController)Director.GetInstance().CurrentSecnController;
            sceneController.gameStatusManager = this;
        }

        public int CheckGame()
        {

            int leftPriests = (sceneController.leftStones.GetCharacterNum())[0];
            int leftDevils = (sceneController.leftStones.GetCharacterNum())[1];
            int rightPriests = (sceneController.rightStones.GetCharacterNum())[0];
            int rightDevils = (sceneController.rightStones.GetCharacterNum())[1];

            if (leftPriests + leftDevils == 6) return 2;
            if ((rightPriests < rightDevils && rightPriests > 0) || (leftPriests < leftDevils && leftPriests > 0))
            {
                return 1;
            }
            return 0; 
        }
    }
}

6. 修改boat.cs和Charactor.cs

这里我们需要把所有和之前moveable类相关联的代码全部删除
boat.cs:

using UnityEngine;

namespace MyNamespace
{
    public class Boat
    {
        
        public readonly Vector3 destination;
        public readonly Vector3 departure;
        public readonly float movingSpeed = 20;
        public readonly Vector3[] departures;
        public readonly Vector3[] destinations;
        public CharacterController[] passengers = new CharacterController[2];

        public GameObject boatObject { get; set; }
        public loc loc { get; set; }

        public Boat()
        {
            // 船的起点和终点
            departure = new Vector3(5, 1, 0);
            destination = new Vector3(-5, 1, 0);
            loc = loc.right;

            departures = new Vector3[] { new Vector3(4.5f, 1.5f, 0), new Vector3(5.5f, 1.5f, 0) };
            destinations = new Vector3[] { new Vector3(-5.5f, 1.5f, 0), new Vector3(-4.5f, 1.5f, 0) };
            boatObject = Object.Instantiate(Resources.Load("Prefabs/Boat", typeof(GameObject)), departure, Quaternion.identity, null) as GameObject;
            boatObject.name = "boat";

            boatObject.AddComponent(typeof(UserGUI));
        }
    }
}

charactor.cs:

using UnityEngine;

namespace MyNamespace
{
    public class Character
    {
        public CoastController stone { get; set; }
        public bool IsOnBoat { get; set; }
        public GameObject Role { get; set; }
        public readonly float movingSpeed = 20;
        public string Name
        {
            get
            {
                return Role.name;
            }
            set
            {
                Role.name = value;
            }
        }

        public Character(string objectName)
        {
            
            if(objectName.Contains("devil"))
            {
                Role = Object.Instantiate(Resources.Load("Prefabs/Devil", typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;
            }
            else 
            {
                Role = Object.Instantiate(Resources.Load("Prefabs/Priest", typeof(GameObject)), Vector3.zero, Quaternion.identity, null) as GameObject;
            }

            
            Name = objectName;
            IsOnBoat = false;
        }
    }
}

以上为所有代码编写内容,展示结果如下:
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值