490 likes | 541 Views
Yingcai Xiao. Yingcai Xiao. Event-driven Programming in Game Development. Why do we need EDP? What is EDP? How to implement EDP? Taking advantages of EDP in gaming development. EDP in Unity3D with examples. How to use C# to implement EDP? How to debug in Unity3D.
E N D
Yingcai Xiao • Yingcai Xiao Event-driven Programming in Game Development
Why do we need EDP? What is EDP? How to implement EDP? Taking advantages of EDP in gaming development. EDP in Unity3D with examples. How to use C# to implement EDP? How to debug in Unity3D
Interaction => events (software notifications of hardware status changes.) Display Device Driver (GDI) Input Device Driver Game (Software)
EDP: Event-driven programmingApplication awaits in an idle state and responds to user requests by calling the corresponding even handlers. EDP • Yingcai Xiao
A menu in C++: char c; bool done = false; while(!done) { cout << “Please make your selection, q to end:” cin >> c; switch(c) { case “+”: add( ); break; case “-”: sub( ); break; case “q”: done = true; break; } } Event Loop Event Mapping & Event Dispatching Event Events Event Handler
Key Components of EDP • Event generators (input devices) • Events • Event loop • Event mapping • Event dispatching • Event handlers • All, but the handlers, are taken care of by the game engine and its underplaying graphics and OS.
Events • Notifications of status changes. • Can be represented in a char, string, encoded number, object oriented message. • Generated by the OS when users interact with input devices. • Sent to the active application (the application owns the active window.) • Queued at the active application’s event queue. • Removed by the application one by one. • Dispatched to the event handlers according to event mapping.
Events • All other events and new incoming events await until the current event is being processed. • The idle “event”is critical event for drawing background animations. • The idle “event” is internally generated when the event queue is empty. • The idle “event” handler draws the the background animation when there is no other pending events. • The idle “event” should be processed promptly in order to avoid delaying the processing of possible upcoming events.
Event handlers • Programs which process the corresponding events. • Usually a call-back function. • e.g. OnMouseMove • Most likely has input arguments, e.g., cursor location. • Note: no new event can be processed when an event handler is running. • Any long-time running animation should be broken into a sequence of short background animations. • Another challenge is to pass a computational value to another event handler, e.g., the idle event handler.
Event Loop • The event loop checks if there is any event (including the idle event) in the queue. • If yes, dispatches the event to its handler. • If not, waits for input. • Or puts an idle event into the queue if there is an idle handler.
Event Mapping • Event mapping is done when the program register an event handler to an event. • Usually at compile time of constructing the game. • Each handler can be registered to multiple events. • More than one handlers can be registered to each event. • Make sure the handlers define proper arguments for the events. • Names of event handlers are case sensitive.
Event Dispatching • Event dispatching is done at runtime. • The dispatcher invokes the corresponding handlers one by one. • Usually in the order of registration. • Most of the time, only one handler is registered for each event.
EDP in Unity3D • Unity game engine supports EDP. • EDP Programming in Unity needs to • (1) Identify “Event Generators” • (2) Identify “Events” to process • (3) Create “Game Objects” to generate events • (4) Create “Data Structures” and “Algorithm” in “Event Handlers” to process events. • (5) Map “Events” to “Event Handlers”
Event Generators • Events can be generated by hardware and software. • Hardware: CLI (Coomand Line Interface): Keyboard GUI (Graphical User Interface): Mouse, Touch Pad, Tilting NUI (Natural User Interface); Kinect, Leap Motion, Software: Collisions between objects Key points in animations
Unity Input Events Hardware Events: need device interface to get the “messages” of corresponding events. e.g. OpenNI for NUI Software Events: created by game engines at specific time selected by the programmers.
Input Events Edit-> Project Setting-> Input
Unity Animation Events (Software Events) Allows you to call functions in the object’s script at specified points in the timeline of an animation. Add a new Animation Event by double-clicking the Event Line or by using the Event button.
GO Event Generation • Collision Events: • Need to enable collider for the GO to handle collision events. • Need to enable capsule collider for GOs of complex shapes. • Animation Events: • Need to generate the event in the animation timeline. • Need to implement a script and connect it to the event.
Game Object – Animation - Events • To create animation: • Window->Animation • Click on the object to be animated. • Component->Miscellaneous->Animation • Name it. • Start recording (the red button in the Animation Window) • Add Curve->Transform->Position • Stop and save.
Animation Event When you add an event, a dialog box will appear to prompt you for the name of the function and the value of the parameter you want to pass to it.
Scripting in Event Handlers • Writing code to control interaction and animation. • Unity supports: • C# for heavy duty programs • JavaScripts for simple interactions • Boo: “compiled Python”, CLI, .NET, Mono compatible • Unreal supports: • C++ • UnrealScript (discontinued)
EDP-Scripting Demo Coding • To create scripts: • Assets->Create->C# Script • Name it in the Assets Pane. public class Test:MonoBehaviour{ void Start () { /* initialization at the start of the application */} void Update ( ) { /* invoked at every frame of drawing */} }
EDP-Scripting Demo Coding • To link the script: • Select the object • Component->Add->Scripts->Name (e.g.test) • The script box will be added to the inspector of the object. • Note all “public” variables will be displayed in the script box. • To link the “Score” viable, drag “Hierarchy->Canvas->scoreText” to the “Score” box.
Unity3D EDP Demo #1 (IGD5) • Download the EDP-Scripting project. • Open it with Unity3D and select scene1. • Object Cylinder and Terrain. • Note: animation1 was created using Unity GUI. • IGD5 script was created to do simulation. • Simulation is animation obeying certain rules, e.g., trajectory of a projectile.
EDP-Scripting Demo • “a” for animation on/off. • “s” for simulation on/off. • “g” for gravitation on/off. • Animation is different when “g” is on and off. • Hit “s” to stop simulation quickly otherwise the object will run off the screen. • Hit “s” to bring the object back to view if it run away. • Score is increased by one when the cylinder hits the terrain.
EDP-Scripting Demo Coding The scoreText object needs to be created beforehand. GameObject->UI->Text
Unity C# Code Example: IGD5.cs (in EDP-Unity4/Assets)
using UnityEngine;using UnityEngine.UI;using System.Collections;public class IGD5 : MonoBehaviour { float time = 0; float threshold = 0.5f; bool isReady = true; bool isSimulate = false; int collisionCount = 0; public Vector3 speed = new Vector3(5,5,0); public GameObject score; // the text object for displaying score // Use this for initialization void Start () { } C# Code Example: IGD5.cs
//colision detection void OnCollisionEnter (Collision collision) { if (collision.gameObject.tag == "terrain") { collisionCount++; score.GetComponent<Text>().text = "Score : " + collisionCount; } } void simulationControl () { transform.position = new Vector3 ( //colision detection void OnCollisionEnter (Collision collision) { if (collision.gameObject.tag == "terrain") { collisionCount++; score.GetComponent<Text>().text = "Score : " + collisionCount; } } void simulationControl () { transform.position = new Vector3 ( transform.position.x + speed.x*Time.deltaTime, transform.position.y + speed.y*Time.deltaTime, transform.position.z); } C# Code Example: IGD5.cs
void Update () { if (!isReady) { if (time >= threshold) { isReady = true; time = 0; } else { time += Time.deltaTime; } } else void Update () { if (!isReady) { if (time >= threshold) { isReady = true; time = 0; } else { time += Time.deltaTime; } } else C# Code Example: IGD5.cs
{ if (Input.GetKey (KeyCode.G)) { if (gameObject.GetComponent<Rigidbody> ()) { gameObject.rigidbody.useGravity = !gameObject.rigidbody.useGravity; } else { gameObject.AddComponent<Rigidbody> (); } isReady = false; } else if (Input.GetKey (KeyCode.A)) { if (animation.isPlaying) gameObject.animation.Stop(); else gameObject.animation.Play (); isReady = false; } C# Code Example: IGD5.cs
else if (Input.GetKey (KeyCode.S)) { ///simulation isSimulate = !isSimulate; //on-off isReady = false; } } //Animation control if (isSimulate) simulationControl(); }} C# Code Example: IGD5.cs
Unity3D EDP Demo #2 EDP-Unity5(source code in EDP-Unity5/Assetsexecutable in EDP-Unity5/SecondBuild)
EDP in Unity5 • Three types of events in this example: • Keyboard (HW) • Collision (SW) • Animation Events (SW) • Events are counted and displayed.
Keyboard Events (HW) • Left/right & (a/d) keys for horizontal movements • Up/Down & (w/s) keys for vertical movements • Hold “g” to experience gravity • Toggle “t” to start/stop animation in a triangular path
Collision (SW) • Each collision increases the event count by 1. • GO color changes as it collides with walls. • Needs to enable collision detection for GO.
Animation Events (SW) • Event added on the animation timeline when the GO reaches the top of the triangular path. (Using the Unity Animation GUI.) • Need to provide a function (the event handler) when creating an animation event.
Communications with the Game Engine • There are three parts of a game value, for example, collision count. • An internal private variable in the event handler to keep track of the collision: “private int count;” • A GO that displays the value of count. • A public variable in the handler linked to the GO (through Unity Inspector): “public Text countText;”
using UnityEngine; using UnityEngine.UI; using System.Collections; public class Player : MonoBehaviour { public float MoveSpeed = 10f; public Text countText; private Rigidbody rb; private Renderer rend; private Light mylight; private Animation myanimation; private int count; void Start () // Use this for initialization { rb = GetComponent<Rigidbody>(); rend = GetComponent<Renderer>(); mylight = GetComponent<Light>(); myanimation = GetComponent<Animation>(); count = 0; SetCountText(); }
void Update () { // Update is called once per frame if (Input.GetKey(KeyCode.G)) { print("g for Gravity"); rb.useGravity = !rb.useGravity; } else if (Input.GetKey(KeyCode.T)) { print("T for play/stop triangle movement"); if (myanimation.isPlaying) { myanimation.Stop(); } else { myanimation.Play(); } } float inputX = Input.GetAxis("Horizontal"); float inputZ = Input.GetAxis("Vertical"); float moveX = inputX*MoveSpeed*Time.deltaTime; float moveZ = inputZ*MoveSpeed*Time.deltaTime; rb.AddForce(moveX, 0f, moveZ); }
void OnCollisionEnter(Collision col) { //collosion detection print(col.collider.name); if(col.collider.name == "FrontWall") { rend.material.color = Color.blue; mylight.color = Color.blue; } else if(col.collider.name == "LeftWall") { rend.material.color = Color.red; mylight.color = Color.red; } else if(col.collider.name == "RightWall") { rend.material.color = Color.yellow; mylight.color = Color.yellow; } else if(col.collider.name == "BackWall") { rend.material.color = Color.green; mylight.color = Color.green; }
else if(col.collider.name == "Floor") { rend.material.color = Color.magenta; mylight.color = Color.magenta; } SetCountText(); } void SetCountText() { count ++; countText.text = "Count:" + count.ToString(); } }
EDP with OpenGL • Unity3D and Unreal (UDK) game engines are based on graphics engines: OpenGL or ActiveX. • Graphics engines deal with output not input. • The event dispatcher invokes the corresponding handlers one by one based on the input events and event registration. • Usually in the order of registration. • Most of the time, only one handler is registered for each event. • Multiple handlers can be registered to the same event.