Difference between revisions of "Module code examples"
(→Useful geometry stuff) |
(→Useful geometry stuff) |
||
Line 113: | Line 113: | ||
It's often useful to transform a vector into a coordinate system affixed to the ship, which will in general be rotated with respect to the world coordinate system. To do this use vessel.transform.InverseTransformDirection( ): | It's often useful to transform a vector into a coordinate system affixed to the ship, which will in general be rotated with respect to the world coordinate system. To do this use vessel.transform.InverseTransformDirection( ): | ||
− | < | + | <syntaxhighlight> |
//angular velocity of the ship around three axes, | //angular velocity of the ship around three axes, | ||
//x-component = pitch rate, y = roll rate, z = yaw rate: | //x-component = pitch rate, y = roll rate, z = yaw rate: |
Revision as of 11:56, 8 March 2012
Here is a collection of example code for various tasks you might want to perform in your module.
Contents
Debugging your code
The most important thing to be able to do! This will print to the in-game error console, which you can bring up from anywhere in the game by pressing Alt-F2:
print("hello world!");
Creating a GUI Window and Button
This module will create a new GUI window and button, on button press the part will explode, close the GUI, and be removed.
using UnityEngine; /* This module will create a new GUI window and button, on button press the part will explode, close the GUI, and be removed. */ public class SelfDestruct : Part { protected Rect windowPos; private void WindowGUI(int windowID) { GUI.DragWindow(new Rect(0, 0, 10000, 20)); //create a dragable window GUIStyle mySty = new GUIStyle(GUI.skin.button); mySty.normal.textColor = mySty.focused.textColor = Color.white; mySty.hover.textColor = mySty.active.textColor = Color.yellow; mySty.onNormal.textColor = mySty.onFocused.textColor = mySty.onHover.textColor = mySty.onActive.textColor = Color.green; sty.padding = new RectOffset(8, 8, 8, 8); //It seems you need to put all buttons between vertical or horizontal GUILayout functions //Without doing this GUILayout.Button() will only be true if you right and left click at the same time GUILayout.BeginVertical(); if (GUILayout.Button("DESTROY",mySty,GUILayout.ExpandWidth(true)))//GUILayout.Button is "true" when clicked { this.explode(); this.onPartDestroy (); this.Die (); } GUILayout.EndVertical(); } private void drawGUI() { GUI.skin = HighLogic.Skin; windowPos = GUILayout.Window(1, windowPos, WindowGUI, "Self Destruct", GUILayout.MinWidth(100)); } protected override void onFlightStart() //Called when vessel is placed on the launchpad { RenderingManager.AddToPostDrawQueue(3, new Callback(drawGUI));//start the GUI } protected override void onPartStart() { if ((windowPos.x == 0) && (windowPos.y == 0))//windowPos is used to position the GUI window, lets set it in the center of the screen { windowPos = new Rect(Screen.width / 2, Screen.height / 2, 10, 10); } } protected override void onPartDestroy() { RenderingManager.RemoveFromPostDrawQueue(3, new Callback(drawGUI)); //close the GUI } }
Useful geometry stuff
All these vectors live in a "world" coordinate system. This coordinate system has an arbitrary orientation and an origin that is periodically shifted to keep it reasonably close to the active ship.
Vector3d has lots of useful vector manipulation methods that you should check out.
//position of the ship's center of mass: Vector3d position = vessel.findWorldCenterOfMass(); //unit vectors in the up (normal to planet surface), east, and north (parallel to planet surface) directions Vector3d eastUnit = vessel.mainBody.getRFrmVel(position).normalized; //uses the rotation of the body's frame to determine "east" Vector3d upUnit = (position - vessel.mainBody.position).normalized; Vector3d northUnit = Vector3d.Cross(upUnit, eastUnit); //north = up cross east double altitude = vessel.mainBody.GetAltitude(position); //ship velocity in an external, non-rotating frame: Vector3d nonRotatingFrameVelocity = vessel.orbit.GetVel(); //velocity as seen in planet's rotating frame Vector3d rotatingFrameVelocity = nonRotatingFrameVelocity - vessel.mainBody.getRFrmVel(position); //local acceleration vector due to gravity: Vector3d geeAcceleration = FlightGlobals.getGeeForceAtPosition(position); //given currentVelocity in rotating frame, find coriolis acceleration: //this first one becomes zero when the game switches out of the planet's reference frame Vector3d coriolisAcceleration = FlightGlobals.getCoriolisAcc(currentVelocity, vessel.mainBody); //this doesn't: Vector3d myCoriolisAcc = -2 * Vector3d.Cross(vessel.mainBody.angularVelocity, currentVelocity); //Moment of inertia of the ship around x, y, and z axes (I think y is always the roll axis): Vector3d MOI = vessel.findLocalMOI(vessel.findWorldCenterOfMass()); //direction in which the ship currently points: Vector3d heading = (Vector3d)vessel.transform.up;
It's often useful to transform a vector into a coordinate system affixed to the ship, which will in general be rotated with respect to the world coordinate system. To do this use vessel.transform.InverseTransformDirection( ):
//angular velocity of the ship around three axes, //x-component = pitch rate, y = roll rate, z = yaw rate: Vector3d angularVelocity = (Vector3d)vessel.transform.InverseTransformDirection(vessel.rigidbody.angularVelocity); //to damp out roll (k is some gain): roll_command = k * angularVelocity.y; //to command the ship to slew towards a given direction, dir (k is some gain): //error will be (0, 1, 0) if dir = heading: Vector3d error = (Vector3d)vessel.transform.InverseTransformDirection((Vector3)dir); yaw_command = k * error.x; pitch_command = -k * error.z;
When you print vectors you may find it useful to first cast them to the Unity type Vector3, which by default only prints one digit past the decimal point, whereas Vector3d prints all the digits. Using Vector3's makes your debugging output much easier to read:
print("position = " + (Vector3)position);
Fly-by-wire
You can control the flight from code as if you were the player using w,a,s,d,q,e or a joystick. In addition to yaw, pitch, roll, and throttle as shown below, the FlightCtrlState class gives access to a few other controls that you can check out.
... protected override void onFlightStart() //Called when vessel is placed on the launchpad { //at the beginning of the flight, register your fly-by-wire control function that will be called repeatedly during flight: FlightInputHandler.OnFlyByWire += new FlightInputHandler.FlightInputCallback(fly); ... } //now this function gets called every frame or something and gives you access to the flight controls private void fly(FlightCtrlState s) { s.yaw = -0.2F; //set yaw input to 20% left s.pitch += 0.3F; //set pitch input to whatever the player has input + 30% s.roll = 0.5F; //set roll to 50% (either clockwise or counterclockwise, try it and find out) s.mainThrottle = 0.8F; //set throttle to 80% //the range of yaw, pitch, and roll is -1.0F to 1.0F, and the throttle goes from 0.0F to 1.0F. //if your code might violate that it's probably a good idea to clamp the inputs, e.g.: s.roll = Mathf.Clamp(s.roll, -1.0F, +1.0F); } ...
Modifying the available warp rates
using UnityEngine; ... TimeWarp timeWarp = (TimeWarp)FindObjectOfType(typeof(TimeWarp)); //documentation claims this function is slow //so call it once and store the reference timeWarp.warpRates[3] = 45; //set the fourth warp rate to be x45 timeWarp.altitudeLimits[3] = 0.5; //set the altitude limit for the fourth warp rate. Is this measured in planetary radii?