Difference between revisions of "Module code examples"
From Kerbal Space Program Wiki
Line 58: | Line 58: | ||
} | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == Modifying the available warp rates == | ||
+ | <syntaxhighlight> | ||
+ | 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? | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | == 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. | ||
+ | |||
+ | <syntaxhighlight> | ||
+ | |||
+ | //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; | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | == 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. | ||
+ | |||
+ | <syntaxhighlight> | ||
+ | ... | ||
+ | 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); | ||
+ | } | ||
+ | ... | ||
</syntaxhighlight> | </syntaxhighlight> |
Revision as of 11:47, 8 March 2012
Here is a collection of example code for various tasks you might want to perform in your module.
Contents
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 } }
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?
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;
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); } ...