3D game - patrol

Factory mode

Factory design pattern is also a commonly used creation pattern in game development. Generally, factory pattern is divided into three more subdivided types: simple factory, factory method and abstract factory.

Significance of factory mode:

The code of the instantiated object is extracted and put into a class for unified management and maintenance, so as to decouple the dependency relationship with the main project. So as to improve the expansibility and maintainability of the project.

Dependency abstraction principle of design pattern

  • When creating an object instance, do not directly the new class, but put the action of the new class in a factory method and return. Some books say that variables do not directly hold references to specific classes.
  • Instead of letting classes inherit concrete classes, they inherit abstract classes or implement interfaces
  • Do not override methods already implemented in the base class

(learned the explanation of the boss: factory mode)

Rules of the game

Use WSAD or direction keys to move the player up, down, left and right. After entering the pursuit of the patrol, you can accumulate one point. If you collide with the patrol, the game ends and you can win after collecting all the crystals on the map.

Game design

  • Create a map and several patrols (using animation);
  • Each patrol takes a convex polygon with 3 ~ 5 sides, and the position data is the relative address. That is, determine the next target position each time and calculate with your current position as the origin;
  • If the patrol collides with an obstacle, it will automatically select the next point as the target;
  • The patrolman will automatically chase the player if he senses the player within the set range;
  • After losing the player's target, continue patrolling;
  • Scoring: players will score one point each time they lose a patrol and collide with the patrol. The game ends;

Programming

Use subscription and publish mode to deliver messages
Factory mode production patrol

Game UML diagram

Implementation part

Project model

On the website Unity3D_ Model_ Resources_ Unit asset store_ Free download - aigei.com download

 AnimatorController

  Implementation code

Factory mode: PatrolFactory.cs

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

public class PatorlFactory : MonoBehaviour {

    //The factory mode is responsible for production, while others are not. Therefore, you can see that this class is only related to roles and has nothing to do with all other codes
    private GameObject player = null;                                      //game player
    private GameObject patrol = null;                                     //patrol
    private List<GameObject> patrolList = new List<GameObject>();        //Patrols being used
    private Vector3[] vec = new Vector3[9];                             //Save the initial position of each patrol

    public GameObject LoadPlayer()
    {
        player = Instantiate(Resources.Load("Prefabs/Player"), new Vector3(0, 9, 0), Quaternion.identity) as GameObject;
        return player;
    }

    public List<GameObject> LoadPatrol()
    {
        int[] pos_x = { -6, 4, 13 };
        int[] pos_z = { -4, 6, -13 };
        int index = 0;

        for(int i=0;i < 3;i++)
        {
            for(int j=0;j < 3;j++)
            {
                vec[index] = new Vector3(pos_x[i], 0, pos_z[j]);
                index++;
            }
        }
        for(int i=0; i < 9; i++)
        {
            patrol = Instantiate(Resources.Load<GameObject>("Prefabs/Patrol1"));
            patrol.transform.position = vec[i];
            patrol.GetComponent<PatrolData>().sign = i + 1;
            patrol.GetComponent<PatrolData>().start_position = vec[i];
            patrolList.Add(patrol);
        }   
        return patrolList;
    }

    //At the end of the game, pause all actions
    public void StopPatrol()
    {
        for (int i = 0; i < patrolList.Count; i++)
        {
            patrolList[i].gameObject.GetComponent<Animator>().SetBool("run", false);
        }
    }
}

  Patrol action: PatrolAction.cs

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

public class GoPatrolAction : SSAction
{
	private enum Dirction { E, N, W, S };
	private float pos_x, pos_z; 
	private float move_length; 
	private float move_speed = 1.2f; 
	private bool move_sign = true;
	private Dirction dirction = Dirction.E; 
	private PatrolData data;

	private GoPatrolAction() { }
	public static GoPatrolAction GetSSAction(Vector3 location)
	{
		GoPatrolAction action = CreateInstance<GoPatrolAction>();
		action.pos_x = location.x;
		action.pos_z = location.z;
		action.move_length = Random.Range(5, 8);
		return action;
	}
	public override void Update()
	{
		if (transform.localEulerAngles.x != 0 || transform.localEulerAngles.z != 0)transform.localEulerAngles = new Vector3(0, transform.localEulerAngles.y, 0);          
		if (transform.position.y != 0)transform.position = new Vector3(transform.position.x, 0, transform.position.z);
		Gopatrol();
		if (data.follow_player && data.wall_sign == data.sign)
		{
			this.destroy = true;
			this.callback.SSActionEvent(this,0,this.gameobject);
		}
	}
	public override void Start(){data  = this.gameobject.GetComponent<PatrolData>();}
	void Gopatrol()
	{
		if (move_sign)
		{
			switch (dirction)
			{
			case Dirction.E:
				pos_x -= move_length;

				break;
			case Dirction.N:
				pos_z += move_length;

				break;
			case Dirction.W:
				pos_x += move_length;

				break;
			case Dirction.S:
				pos_z -= move_length;

				break;
			}
			move_sign = false;
		}
		this.transform.LookAt(new Vector3(pos_x, 0, pos_z));
		float distance = Vector3.Distance(transform.position, new Vector3(pos_x, 0, pos_z));
		if (distance > 0.9){transform.position = Vector3.MoveTowards(this.transform.position, new Vector3(pos_x, 0, pos_z), move_speed * Time.deltaTime);
		}else
		{
			dirction = dirction + 1;
			if(dirction > Dirction.S)dirction = Dirction.E;
			move_sign = true;
		}
	}
}

Tracking action: PatrolFollowAction.cs

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

public class PatrolFollowAction : SSAction
{
	private float speed = 2f;
	private GameObject player;
	private PatrolData data;
	private PatrolFollowAction() { }
	public static PatrolFollowAction GetSSAction(GameObject player)
	{
		PatrolFollowAction action = CreateInstance<PatrolFollowAction>();
		action.player = player;
		return action;
	}
	public override void Update()
	{
		if (transform.localEulerAngles.x != 0 || transform.localEulerAngles.z != 0)transform.localEulerAngles = new Vector3(0, transform.localEulerAngles.y, 0);          
		if (transform.position.y != 0)transform.position = new Vector3(transform.position.x, 0, transform.position.z);
		Follow();
		if (!data.follow_player || data.wall_sign != data.sign)
		{
			this.destroy = true;
			this.callback.SSActionEvent(this,1,this.gameobject);
		}
	}
	public override void Start(){data = this.gameobject.GetComponent<PatrolData>();}
	void Follow()
	{
		transform.position = Vector3.MoveTowards(this.transform.position, player.transform.position, speed * Time.deltaTime);
		this.transform.LookAt(player.transform.position);
	}
}

Action management: PatrolActionManager.cs

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

public class PatrolActionManager : SSActionManager, ISSActionCallback
{
	private GoPatrolAction go_patrol;  
	public void GoPatrol(GameObject patrol)
	{
		go_patrol = GoPatrolAction.GetSSAction(patrol.transform.position);
		this.RunAction(patrol, go_patrol, this);
	}
	public void DestroyAllAction(){DestroyAll();}
    public void SSActionEvent(SSAction source, int intParam = 0, GameObject objectParam = null)
    {
        if (intParam == 0)
        {
            PatrolFollowAction follow = PatrolFollowAction.GetSSAction(objectParam.gameObject.GetComponent<PatrolData>().player);
            this.RunAction(objectParam, follow, this);
        }
        else
        {
            GoPatrolAction move = GoPatrolAction.GetSSAction(objectParam.gameObject.GetComponent<PatrolData>().start_position);
            this.RunAction(objectParam, move, this);
            Singleton<GameEventManager>.Instance.PlayerEscape();
        }
    }
}

Tags: html5 html css

Posted on Mon, 29 Nov 2021 04:08:52 -0500 by psyion