3D games (4)-game objects and graphics basis

1. Basic operation exercise [recommended]

Download Fantasy Skybox FREE and build your own game scene

Add Fantasy Skybox FREE to my resources, go to Package Manager from Unity's Window option to download Fantasy Skybox FREE and import it into Asset.

Insert picture description here

First create a sky box, right-click Create a Material in Assert and name it Sky.

Then set the Material Shader to Skybox/Panoramic, then select a suitable picture from the downloaded material and paste it into Spherical, and finally drag the skybox into the scene.

Insert picture description here

Insert picture description here

Then create a terrain, GameObject->3D Object->Terrain. First create a light floor, and then slowly draw mountains, grass, trees, etc. through Terrain's various tools.

Insert picture description here

Insert picture description here

Outcome:

Insert picture description here

It seems okay (×), it's really hard to say (√)

Write a simple summary to summarize the use of game objects

The game object itself is used as a container for components, and different functions can be called by adding different components to it. When an object has a component mounted, it has the relevant properties of the component.

At the same time, different game objects have their unique functions. such as:

  • Camera: As the eyes of the game, it is the medium through which players observe the game world;
  • Light: Light source, which can be used for lighting or adding shadows;
  • Empty object: mostly used as a carrier, such as mounting game scripts, becoming the parent object of other objects, etc.
  • Cube and other 3D Objects: build the elements of the game world, and transform their Position, Rotation, and Scale by setting their properties such as Transform;
  • Terrain, etc.: It is not only a constituent element, but also an editing tool. Terrain itself is a map, and then comes with various tools for drawing maps (building mountains, planting trees and grass, etc.).

2. Programming practice

Priest and Devil Action Separate Version

Design a referee class, when the game reaches the end condition, notify the scene controller that the game is over.

First of all, to realize the priest and the devil of the action separation version based on the previous homework , it is necessary to add action management related classes on the original basis.

The previous job has implemented a Move and a MoveController to manage the action. But this is just a simple action management class. What needs to be implemented this time is more detailed action management.

Insert picture description here

Insert picture description here

Therefore, the most basic need to add SSAction, CCMoveToAction, CCSequenceAction, ISSActionCallback, SSActionManager, CCActionManager these categories.

Here, because my character actions are almost straight-line movements, CCSequenceAction is not implemented because of laziness .

1. First, implement SSAction.

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

    // Start is called before the first frame update
    public virtual void Start(){
        throw new System.NotImplementedException();
    }

    // Update is called once per frame
    public virtual void Update(){
        throw new System.NotImplementedException();
    }
}

Here, ISSACtionCallback is used to realize the notification of the message, and the virtual method is used to declare the virtual method, and polymorphism is realized by rewriting.

2.CCMoveToAction。

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;
    }

    // Start is called before the first frame update
    public override void Start()
    {
        
    }

    // Update is called once per frame
    public override void Update()
    {
        this.transform.localPosition=Vector3.MoveTowards(this.transform.localPosition,target,speed*Time.deltaTime);
        if(this.gameObject==null||this.transform.localPosition==target){
            this.destroy=true;
            this.callback.SSActionEvent(this);
        }
    }
}

This type of inheritance is SSAction, which implements relatively simple movement.

3. ISSActionCallback interface.

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

The code on the teacher's courseware is copied from beginning to end.

4. SSActionManager action management base class.

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

    // Start is called before the first frame update
    protected void Start()
    {

    }

}

The teacher's code is still being copied.

  1. SSActionManager is the manager of action generation, operation and destruction.
  2. Actions store the running actions in the form of a dictionary.
  3. What waitingAdd saves is the action that is about to be executed.
  4. WaitingDelete saves the action that is about to be deleted.
  5. Update() will add the actions in waitingAdd to actions every time, and then traverse the actions in actions and run each action. If the action has ended, it is added to waitingDelete, and finally the action in waitingDelete is deleted and destroyed.

5. CCActionManager action manager.

public class CCActionManager : SSActionManager, ISSActionCallback
{
    private bool isMoving=false;
    public CCMoveToAction moveObjAction;
    public FirstController controller;

    protected new void Start()
    {
        controller=SSDirector.getInstance().currentSceneController as FirstController;
    }

    public bool IsMoving(){
        return isMoving;
    }
    public void MoveObj(GameObject obj,Vector3 target,float speed){
        if(isMoving) return;
        isMoving=true;
        moveObjAction=CCMoveToAction.GetSSAction(target,speed);
        this.RunAction(obj,moveObjAction,this);
    }
    public void SSActionEvent(SSAction source,
        SSActionEventType events=SSActionEventType.Competed,
        int intParam=0,
        string strParam=null,
        Object objectParam=null){
            isMoving=false;
        }
}

At this point, the code on the teacher's courseware is not suitable, and it is best to modify it slightly according to your actual situation. I have to copy it directly

CCActionManager has a large intersection with the previous Move and MoveController. The main function is to provide FirstController with a functional interface for moving game objects.

After implementing a series of action management classes, the original code needs to be modified next.

If the goal is only to be able to run, just change FirstController's original call to MoveController related functions to functions in CCActionManager. Comment out the original MoveController, and mount the CCActionManager script in the Awake() function this.gameObject.AddComponent<CCActionManager>();, so that it can run normally.

However, there is also a requirement for the subject to implement a referee class, when the game reaches the end condition, notify the scene controller that the game is over. That is to say, separate the function of judging the end of the game in the original FirstController, and implement a Judgment class to complete it.

In fact, for convenience ( lazy ), four variables leftPriestNum, leftDevilNum, rightPriestNum, and rightDevilNum are stored in FirstController to judge the game state. However, after separating the Check function, it is obviously inappropriate to store these four variables in FirstController. After all, it should be put in LandModel. At the same time, the initialization of these four variables is also placed in the CreateLand function in LandModelController.

Then, in Judgement, LandModelController is used to obtain the number of priests and devils on both sides of the river.

public class Judgement : MonoBehaviour
{

    private FirstController controller;
    private LandModelController landRoleController;

    // Start is called before the first frame update
    void Start()
    {
        controller=SSDirector.getInstance().currentSceneController as FirstController;
        landRoleController=controller.GetLandModelController();
    }

    // Update is called once per frame
    void Update()
    {
        if(!controller.GetIsRuning()) return;
		this.gameObject.GetComponent<UserGUI>().gameMessage="";
		if(landRoleController.GetLandModel().rightPriestNum==3&&landRoleController.GetLandModel().rightDevilNum==3){
            controller.JudgeCallback(false,"You Win!!");
		}
		else if((landRoleController.GetLandModel().leftPriestNum!=0
            &&landRoleController.GetLandModel().leftPriestNum<landRoleController.GetLandModel().leftDevilNum)
			    ||(landRoleController.GetLandModel().rightPriestNum!=0
            &&landRoleController.GetLandModel().rightPriestNum<landRoleController.GetLandModel().rightDevilNum)){
			    controller.JudgeCallback(false,"Game Over!!");
		    }
    }
}

In essence, put the original Check function in the update() function, change the name of the quantity, and finally call the related callback function JudgeCallback. (FirstController also needs to add GetIsRuning() and GetLandModelController() two functions)

Finally, comment out the original statements related to the Check() function, and then mount the Judgement script in the Awake() function of FirstController this.gameObject.AddComponent<Judgement>();.

Insert picture description here

I originally thought of using the game scene I built before, but the effect is really true. . . It would be better to use the original scene.

Finally, attach the complete code

3. Contact between materials and rendering [optional]

Standard Shader natural scene renderer.

Create a new "ball" in the scene, then create a new Material in the Asset and drag it to the sphere.

Insert picture description here

First you can change the color at Albedo.

Insert picture description here

Insert picture description here

Check the Rendering Mode as Transparent mode and modify the A value of Color in Albedo to change the transparency of the sphere.

Insert picture description here

Insert picture description here

You can also change the value of Metallic to give it a metallic feel.

Insert picture description here

Insert picture description here

You can also change the value of Smoothness.

Insert picture description here

Insert picture description here

Insert picture description here

Insert picture description here

Uh. . It's hard to say a word after it's full. .

sound

  • Read the official Audio manual
  • Use a blog to give a case of using Reverb Zones in the game to present the sound effect of a vehicle passing through a tunnel

Download car audio

Directly on the sphere in front ( lazy ), AddComponent->Audio->Audio Source and Audio Reverb Zones, drag and drop the downloaded audio to the audio source.

Insert picture description here

Then set the Reverb Preset of the Reverb Zone to Cave.

Insert picture description here

Just click to run.

Guess you like

Origin blog.csdn.net/qq_43278234/article/details/108967361