500 likes | 548 Views
Learn the differences between C# and JavaScript for Unity animation scripting. C# offers OOP support, while JavaScript is ideal for simple animations. Explore data types, classes, properties, and more. Master the basics with tutorials and examples.
E N D
C# forUnity3D Yingcai Xiao
Unity3D & C# • Unity uses two programming languages for coding animation scripts: JavaScript and C# • JavaScript for simple animations, it has no support for OOP. • C# for sophisticated animations, supports OOP & EDP, platform independent.
http://www.learncs.org/ https://www.tutorialspoint.com/csharp/ http://csharp.net-tutorials.com/basics/introduction/ http://csharp.net-tutorials.com/debugging/introduction/ https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/index http://www.completecsharptutorial.com/ https://www.javatpoint.com/c-sharp-tutorial https://www.youtube.com/watch?v=lisiwUZJXqQ http://www.tutorialsteacher.com/online-test/csharp-test C# References
Part I Moving from C++/Java to C#
Data Types in (CTS) System-defined Types (SDTs): Primitives (int, float, …) User-defined Types (UDTs): Classes Properties Structs Interfaces Enumerations Events Delegates Generics Templates
Classes Class: a group of code and data to be instantiated to form objects. Four categories of class members: Fields: member variables Methods: member functions Properties: fields exposed using accessor (get and set) methods Events: notifications a class is capable of firing
Example: How to define a class (user-defined data type) class Rectangle { // Fields protected int width = 1; protected int height = 1; // Methods public Rectangle () { } public Rectangle (int cx, int cy) { width = cx; height = cy; }
Example: How to define a class (user-defined data type) // Accessor Methods public void setWidth(int w) { width = w; } public int getWidth() { return width; } public void setHeight(int h) { height = h; } public int getHeight() { return height; } public int area() { int a; a = height*width; return a; } } // End of Rectangle class
Example: How to use a class (user-defined data type) Rectangle rect = new Rectangle(2,4); rect.setHeight(8); rect.setWidth(rect.getWidth() * 2); double darea = (double) rect.area();
Data types describe the memory layout of objects. • The name of an object is the name of the memory space stores its data value. • For example, inti = 8; “i” is the name of the memory space for storing the data value 8. i What is Data Type?
A pointer in C++ is a memory location that stores an address. Rectangle *rect = new Rectangle (3, 4); rect 0x12345678 C++ Pointer • Dereferencing rect-> int area = rect->Area(); • Please note the notation difference between a “pointer/reference” and a “name” in this lecture.
A method is a (function) pointer that points to the code location of the method in the “text” memory, i.e., the pointer stores the address of the code location of the method in the “text” memory. Area 0x01234567 (text memory) C++ Function Pointer http://www.cs.uakron.edu/~xiao/ics-f99/fun-ptrs.html
Class Name; In CTS:“Rectangle rect” declares a reference of class Rectangle. rect “rect” is the name of a memory space that stores a reference. This is similar to Java. Instantiating a Class (in CTS & C#) A “reference” is an internal pointer, it needs to “point” to an object before being dereferenced.
Rectangle rect = new Rectangle (3, 4); // Use the second constructor rect 0x12345678 References in C# • Dereferencing int area = rect.Area();
The root class of all other classes. • So, an object of any class is an “Object” So we can write: Object obj = new Rectangle (3, 4); • Constructor: Object () • String output: ToString() • Read matadata: GetType() • Clean up: Finalize() • https://msdn.microsoft.com/en-us/library/system.object%28v=vs.110%29.aspx The “Object” class
System.Object : root class for all other classes. • Every class inherits the Finalize( ) method from System.Object. • It is called just before an object is destroyed by the garbage collector of CLR. • The time of call is determined by CLR not by the program. • Use System.GC.Collect() to force a garbage collection (system wide, time consuming). • Destructor in C++ is called just before an object is destroyed by the program, when the object is freed (for heap objects) or out of scope (for stack objects). The Object Class: System.Object
C# Part II Beyond C++/Java
Property Can we make the member fields secure and easy to use at the same time?
Encapsulation and convenience We protected member fields: width and height. (Encapsulation) (1) Securer code. Methods not belonging to the class hierarchy can’t access protected members. If we don’t want anyone change the value of “width”, we just don’t provide the setWidth() method. (2) Easier to maintain the code. We can rename “width” to “w” without impacting the users of the “Rectangle” class. (3) Tedious to implement and use. If we define the member fields as public, the usage would be much easier. rect.width *= 2;
Example: Accessor Methods for Protected Fields class Rectangle { // Fields protected int width = 1; protected int height = 1; // Methods public Rectangle () { } public Rectangle (int cx, int cy) { width = cx; height = cy; }
Example: How to define a class (user-defined data type) // Accessor Methods public void setWidth(int w) { width = w; } public int getWidth() { return width; } public void setHeight(int h) { height = h; } public int getHeight() { return height; } } // End of Rectangle class
Example: How to use a class (user-defined data type) Rectangle rect = new Rectangle(2,4); rect.setHeight(8); rect.setWidth(rect.getWidth() * 2); double darea = (double) (rect.getWidth() * rect.getHeight() );
A new construct in C# named “Property” makes member fields secure and easy to access at the same time.
Example: How to define properties // Properties defined as grouped accessor methods // in the Rectangle class public int Width // group name { get { return width; } set // the input parameter is implicit: value { if (value > 0) width = value; else throw new ArgumentOutOfRangeException ( "Width must be 1 or higher"); } }
public int Height // a field defined by type and accessor code { get { return height; } set { if (value > 0) height = value; else throw new ArgumentOutOfRangeException ( "Height must be 1 or higher"); } } Example: How to define properties
Example: How to define properties public int Area // a property of only get method { get { return width * height; } }
Defining Properties • Properties are defined in the following format: protected type field-name; public type property-name { get { /* return the field value */ } set { /* reset the field value */ } } • A property definition is composed of • a protected or private field • a property to expose the field • which in turn consists of at least one accessor (get()/set()).
Using Properties • Properties are used the same way as public fields. Rectangle rect = new Rectangle(2,4); rect.Width = 7; rect.Width *= 2; // Double the rectangle's width int area = rect.Area; // Get the rectangle's new area //Typecast a property “value” from int to double double darea = (double) rect.Area; • Advantage of Properties: allow users to access private/protected fields as if they were public fields.
Notes on Properties • Properties are public methods (set and get) used like fields. Data is secured (encapsulated) and access is simplified. (2) The set and get methods are called accessors. A property may not have the set (read-only properties) or the get (write-only properties), but can not miss both. (3) The implicit input argument, value, for the set method has the same type as the property. (4) The type of a property must be the same as the type of the field member it protects. (5) A property can’t be overloaded, e.g., we can’t define a “public double Area { … }” after defining “public int Area { … }”. You have to use a different property name, e.g. doubleArea, to define the area property of type double.
Signature of a method: name, number of arguments, types of the arguments. Return type is not part of the signature. • Overloading: two or more methods have the same name but different arguments. • Name Mangling encodes the name of an overloaded method with its signature (by the compiler). The internal names of the methods are unique (no internal overloading). Why we have to name properties of different types differently? • Property do not have any arguments, so the only way to differentiate properties of different type is by their names.
Arrays in C++ int a[2]; a[0] = 5; a[1] = 10; // stack objects , size has to be known at compile time and can’t be changed at runtime. int size = 2; int *p; // a pointer p = new int[size]; p[0] = 5; p[1] = 10; // heap objects; dynamically allocated at runtime, “size” can be a variable delete p; // free the memory. a p
Array (same syntax for both class and struct): Point[] pa = new Point[2]; pa[0] = new Point(); pa[1] = new Point(); Console.WriteLine ("pa[0] = ({0}, {1})", pa[0].x, pa[0].y); Console.WriteLine ("pa[1] = ({0}, {1})", pa[1].x, pa[1].y); Challenges: (1) Draw pictures to show the memory layout of pa for Point as a class and a struct. (2) What will happen when lines 2 and 3 are removed. Explain what will happen for Point as a class and then as a struct. Arrays in CTS
class Parent { int i; setParent(int k) {i=k;} } class Child: Parent{ int j; public setChild(int m, int n) {i=m; j=n;} } Parent p1 = new Parent (); p1.setParent(1); Child c1 = new Child(); c1.setChild(2,3); // child objects can be treated as parent objects Parent p2 = (Parent) c1; p2.setParent(4); // don’t do this!!! parent objects can’t be treated as child objects Child c2 = (Child) p1; c2.setChild(5,6); Typecast References
class Parent { int i; public void move(int k) {i=k;} } class Child1: Parent { public void move(int k) {i=k;} } class Child2: Parent { public void move(int k) {i=2*k;} } Parent [] oa = new Parent[2]; foreach (Parent p in oa) p.move(4); Parent p = new Parent(); c1 = p; c1.move(4); Upcasting Arrays
class Parent { int i; public void move(int k) {i=k;} } class Child1: Parent { public void move(int k) {i=k;} } class Child2: Parent { public void move(int k) {i=2*k;} } Child1 c1 = new Child1(); Child2 c2 = new Child2(); Parent [] oa = new Parent[2]; oa[0] = c1; oa[1] = c2; foreach (Parent p in oa) p.move(4); Upcasting Arrays
You can typecast a child reference to parent reference, but never typecast a parent reference to a child reference. When we typecast the references, we do not alter the underlying objects (memory for the data.) Class type determines the memory layout. A child class inherits from its parent class, but not the other way around. A parent class does NOT inherit anything from its child classes. An object is an instance of a class, a real memory has the layout specified by the class. An object of a child type is an object of the parent type, but not the other way around. An object of a parent type is NOT an object of the child type. Typecast References class Parent { int i; Parent(int k) {i=k;) } class Child: Parent{ int j; public set(int m, int n) {i=m; j=n;} } Parent p1 = new Parent (1); Child c1 = new Child(); C1.set(2,3); Unboxing is narrowing and has to be explicitly casted.
More on C# Part III Event and Delegate
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 Event Mapping & Dispatching Event Handler Events
• .NET supports the development of GUI (Graphical User Interface) based EDPs (event-driven programs). • Event loop and event mapping for such applications can be very complicate. • .NET internally implemented the event loop and event mapping mechanism for such applications. • The development of GUI-based applications in .NET needs only to design the GUI and write event handlers. Events & Delegates
• How can we register event handlers written by us to the event loop written by Microsoft? • The system event loop was implemented before the application event handlers and the names of the handlers are not pre-specified. • Event handlers are also called “callback methods”. Events are also called messages. • .NET implement this by using event & delegate constructs. Events & Delegates
• A delegate is a type-safe wrapper around a callback method. • Callback methods are used to respond to events. • Three steps to understand events & delegates using an example • Define a callback method to use a predefined Timer class • Exam the Timer class which uses event & delegate • Analyze the internal code of delegate Events & Delegates
// Call this callback method every 6 seconds. void UpdateData (Object sender, ElapsedEventArgs e) { // Update Data every 6 seconds. } // A Timer class has been implemented for us to use. // It has an event: Elapsed. Timer timer = new Timer (6000); timer.Elapsed += new ElapsedEventHandler (UpdateData); We registered a function pointer, UpdateData, as a callback, created a new instance of ElapsedEventHandler (a delegate) that wraps around (delegates to) UpdateData (a callback method) to respond to the Elapsed event. Usage of a Predefined Timer Class
Inside the Timer class: public delegate void ElapsedEventHandler (Object sender, ElapsedEventArgs e); // specifies arguments for the callback public class Timer { public event ElapsedEventHandler Elapsed; … } // Calling the callback methods when the event occurs if (Elapsed != null) // Make sure somebody's listening, use Elapsed as a reference. Elapsed (this, new ElapsedEventArgs (...)); // Fire! Use Elapsed as a method, its arguments are sent to the callback methods. Defining Events & Delegates
• A delegate is defined by placing the key word, delegate, in front of a global method. • The arguments of the method in the declaration are those of the callback functions. • The “real” argument of a delegate is always a pointer (to the callback function). • In the declaration of an event object, the type specifier between the “event” key word and the object name specifies the delegate to be used by the event to invoke event handlers. • An event object can be used as a reference and a method. • When an event object is used as a method, its arguments are sent to the callback methods, which are specified by the related delegate. Events & Delegates cont.
public delegate void ElapsedEventHandler (Object sender, ElapsedEventArgs e); Compiles to: public class ElapsedEventHandler : MulticastDelegate // System.MulticastDelegate { public ElapsedEventHandler (object target, int method) { ... } public virtual void Invoke(object sender,ElapsedEventArgs e) { ... } ... } Use an event’s instance name as a method, actually call the Invoke method. It is a better way (a type safe way) to implement function pointers. (http://www.cs.uakron.edu/~xiao/ics/fun-ptrs.html). What’s Inside Events & Delegates?
What is it? How to define and use it? Can you write a program? Can you trace a program? Do you know what’s going on inside? The Fundamentals of C#