Unity3D course study notes (3)

1. Fantasy Skybox FREE Build your own game scene

In fact, this operation is very simple, as long as you search for Fantasy Skybox FREE in the Asset Store, then add Component in Camera, then add Skybox, and then add the corresponding Skybox pattern to complete it.

For the specific operation of adding a skybox, please refer to the illustration on the left below, and add the component Component->Rendering->Skybox in the main camera Main Camara.

    

After adding this component, you can see the property bar as shown on the right above, there is a Custom Skybox property, drag your favorite skybox model into it, and then press Run, you can get your favorite scene Now, I see a more realistic picture, which is much better than the background created by the box made by the solar system last time, and also saves the background loaders of the priest and the devil below.

The effect diagram is as follows:

This is a schematic diagram of the scene after adding Terrain. You can create some of your own scenes in Terrain. The specific methods can be seen in the following diagram. In these settings, after adding your own assets, you can create You can create your favorite tree, grass, floor and other styles, and such a game environment can be roughly created, and you don't have to write code yourself in this process.

2. Game Object Summary

Game objects mainly include: empty objects, cameras, rays, 3D objects, sounds, UI event-based new UI systems and particle systems and special effects
- Empty objects (Empty): not displayed but one of the most commonly used objects
- Camera (Camara ): A window to observe the game world-
Light: The light source of the game world, making the game world attractive-
3D objects: An important part of a 3D game, its mesh and material can be changed, the triangle mesh is the surface of the game object The only form of
- Audio: the source of sound in 3D games

3. Programming practice, separated version of priest and devil action

This job needs to separate the actions in the field record on the basis of the previous job. First, create an action manager

Action management is an important part of the game content. In this assignment, we need to figure out the combination of simple actions, implement the action manager, implement the basic action class, and call back to realize the action completion notification (classical method). The UML diagram of its planning and design is as follows Show:

The design of the action base class (SSAction), in the following code

ScriptableObject is a programmable base class that does not require binding GameObject objects. These objects are managed by the Unity engine scene

protected SSAction() is to prevent users from new objects

Use virtual to declare virtual methods and implement polymorphism by overriding. This allows inheritors to explicitly use Start and Update to program game object behavior

Use the interface to implement message notification to avoid direct dependence on the action manager

The relevant code for SSAction is as follows:

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() {}

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

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

In the action-separated version of priest and demon, action separation is achieved by writing specific action classes, which are managed by action managers, and then assign actions to the objects passed in.

In the following code, polymorphism is achieved by rewriting Update and Start. After the action is completed, set the destroy of this SSAction to true, and notify the manager of message delivery, so that the action can be destroyed and recycled.

The function of CCMoveToAction is mainly to move the action in the game. By passing in the position of the game object and the set action, the game object can be moved.

The relevant code for CCMoveToAction looks like this:

public class CCMoveToAction : SSAction {
	public Vector3 target;
	public float speed;

	public static CCMoveToAction GetSSAction(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);
		if(this.transform.position == target) {
			this.destroy = true;
			this.callback.SSActionEvent(this);
		}
	}

	public override void Start() {}
}

Next is the class CCSequenceAction implemented by the combined action. This class creates an action sequence execution sequence. In the following code, the value of repeat is -1 to indicate that the action is infinitely looped, and start indicates that the action starts.

The rewrite of Update means to execute the current action

The SSActionEvent is a callback notification action. When the current action is completed, the next action is pushed. If the cycle is completed, the number of times is reduced. If and when all actions are complete, notify the action's manager and destroy it.

The rewrite of Start means that before executing the action, inject the game object of the current action for each action, and use itself as the receiver of the action event.

The relevant code for the SSActionEvent is as follows:

public class CCSequenceAction : SSAction, ISSActionCallback {
    public List<SSAction> sequence;
    public int repeat = -1; //repeat forever
    public int start = 0;

    public static CCSequenceAction GetSSAction(int repeat, int start, List<SSAction> sequence) {
        CCSequenceAction action = ScriptableObject.CreateInstance<CCSequenceAction>();
        action.repeat = repeat;
        action.sequence = sequence;
        action.start = start;
        return action;
    }

    public override void Start() {
        foreach (SSAction action in sequence) {
            action.gameobject = this.gameobject;
            action.transform = this.transform;
            action.callback = this;
            action.Start();
        }
    }

    public override void Update() {
        if (sequence.Count == 0) return;
        if (start < sequence.Count)
            sequence[start].Update();
    }

    public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Completed,
     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);
            }
            else {
                sequence[start].Start();
            }
        }
    }

    private void OnDestroy() {
        //destory
    }
}

Next is the code analysis of the action event interface. After defining the time processing interface, all event managers must implement this interface to implement event scheduling. So, a composite event needs to implement it, and so does the event manager.

The relevant code for SSActionEventType is as follows:

public enum SSActionEventType : int { Started, Completed }

public interface ISSActionCallback
{
    void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Completed,
        int intParam = 0, string strParam = null, Object objectParam = null);
}

Then comes the design of the action manager. The function of RunAction in the action manager is to provide a new action method, and this method binds the game object to the action and binds the message receiver of the action event. The relevant code is as follows:

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>();

    void Start() {}

    protected void Update() {
        foreach (SSAction ac in waitingAdd) actions[ac.GetInstanceID()] = ac;
        waitingAdd.Clear();

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

        foreach (int key in waitingDelete) {
            SSAction ac = actions[key]; actions.Remove(key); DestroyObject(ac);
        }
        waitingDelete.Clear();
    }

    public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager) {
        action.gameobject = gameobject;
        action.transform = gameobject.transform;
        action.callback = manager;
        waitingAdd.Add(action);
        action.Start();
    }
}

The last is the key case. Personally, the above content is equivalent to a template. The real application is the following CCActionManager, which can specifically run related objects.

For example, the moveBoat action was originally implemented in the FirstController by calling the Move() method, but after the action is separated, the action manager manages the Move action, and returns an instance of SSAction in the CCActionManager to transfer the parameters of the corresponding motion Transfer to this action instance, and then associate the game object with the action through RunAction, so as to achieve the effect of game object movement.

The movement of the priest or the devil is executed in two parts. One part, such as the uploading action, is moved horizontally to the top of the ship, and then moved vertically. Therefore, there are two actions, action1 and action2, which are added to the In the action list, 1 means execute only once, and 0 means start. Other parts are the same as the execution process of a single action.

public class CCActionManager : SSActionManager, ISSActionCallback
{
    public FirstController sceneController;
    public CCMoveToAction MoveBoatAction;
    public CCSequenceAction MoveCharacterAction;

    // Use this for initialization
    protected void Start () {
        sceneController = (FirstController)Director.getInstance().currentScenceController;
        sceneController.actionManager = this;
    }

    public void moveBoat(GameObject boat, Vector3 target, float speed) {
        MoveBoatAction = CCMoveToAction.GetSSAction(target,speed); //将相应的参数传递给SSAction实例
        this.RunAction(boat, MoveBoatAction, this);//通过调用RunAction将游戏对象和动作联系起来,实现动作
    }

    public void moveCharacter(GameObject character, Vector3 middle, Vector3 end, float speed) {
        SSAction MoveToMiddle = CCMoveToAction.GetSSAction(middle,speed);
        SSAction MoveToEnd = CCMoveToAction.GetSSAction(end,speed);
        MoveCharacterAction = CCSequenceAction.GetSSAction(1, 0, new List<SSAction>{ MoveToMiddle, MoveToEnd });
        this.RunAction(character, MoveCharacterAction, this);
    } 

    public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Completed,
        int intParam = 0, string strParam = null, Object objectParam = null) {}
}

The other parts of the code are actually similar to the code of the last job, except that the relevant code in the moveablescript is removed and handed over to the action manager for management, and then I do some merging operations on the classes of the last code. The specific code can be found on my Github .

Finally, I uploaded a rendering of the game. In fact, it is similar to the last homework, but there are a few more bugs. In fact, this homework is really difficult. Many codes have to be borrowed from others. Out, many places still do not understand.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324075613&siteId=291194637