Cephei

The official unoffical "help a fellow plugin developer" thread

Recommended Posts

In onPartLoad() I\'m walking the Transform tree and any node name starting with 'node_collider' I create a MeshCollider for and delete the MeshRenderer from. The game seems to do this automatically for the one node named (exactly) 'node_collider' and it renames it to 'collider' at the same time (at least that\'s the state everything\'s in when my onPartLoad() is called).

The good news is this seems to work -- my unfolded solar panels will happily collide with objects.

Next step, I want to figure out how to adjust the drag so unfolding them while in flight becomes a really bad idea (ideally they should not survive the event, being torn off the craft). When folded up against the side of the ship, they should add some, but not a catastrophic amount of drag.

spaaace.jpg

Share this post


Link to post
Share on other sites

Do you mind sharing your implementation of the folding? It would be nice to see how you implemented it, as I\'m planning on making some more dynamic parts in the near future.

Share this post


Link to post
Share on other sites
Todo:

- figure out why the model draws incorrectly in the VAB parts bay

It seems that KSP does not instantiate part\'s class when drawing its VAB icon, it uses the mesh as it is. Paint additional colliders\' texture fully transparent (with alpha channel exactly zero) to make them invisible; and set alphaCutoff parameter in Part.cfg to some positive value (0.1 would be OK).

P.S. Excellent work with MeshColliders!

It\'s a shame I can\'t do the same with my WheelColliders; they wanna have a rigidbody at the moment of their creation :(

Share this post


Link to post
Share on other sites

how do you make a part apply a force in a certain direction?

Also how do you find the current gravitational acceleration?

Share this post


Link to post
Share on other sites

how do you make a part apply a force in a certain direction?


//the direction is the part\'s up vector
forceDirection = this.transform.up.normalized;
forceMagnitude= 10;

//apply the force
this.rigidbody.AddForceAtPosition(forceDirection*forceMagnitude, this.transform.position,UnityEngine.ForceMode.Force);

Also how do you find the current gravitational acceleration?


gvector = -FlightGlobals.getUpAxis(this.vessel.transform.position);
gmagnitude = FlightGlobals.getGeeForceAtPosition(this.transform.position);
gravity = gvector.normalized * gmagnitude;

There\'s also this value, but I\'m not sure what it does if you have more than one active ship.

FlightGlobals.ship_geeForce

Share this post


Link to post
Share on other sites

There\'s also this value, but I\'m not sure what it does if you have more than one active ship.

FlightGlobals.ship_geeForce

Thanks

I am trying that out of gravity code and I am getting the error

Error 1 Operator \'*\' cannot be applied to operands of type \'Vector3d\'

about this line

gravity = gvector.normalized * gmagnitude;

gmagnitude is a 3d vector how do i get the scaler out of it?

Share this post


Link to post
Share on other sites

how do you make a part apply a force in a certain direction?

Also how do you find the current gravitational acceleration?

1. base.Rigidbody.AddForceAtPosition(Vector3);

2. I\'m not sure, but I think it\'s in this.orbit somewhere.

Share this post


Link to post
Share on other sites

Thanks

I am trying that out of gravity code and I am getting the error

Error 1 Operator \'*\' cannot be applied to operands of type \'Vector3d\'

about this line

gravity = gvector.normalized * gmagnitude;

gmagnitude is a 3d vector how do i get the scaler out of it?

It is? Then that\'s all you need.


gravity = FlightGlobals.getGeeForceAtPosition(this.transform.position);

Share this post


Link to post
Share on other sites

Hey guys, a newbies question:

Do we know the order of function calls on part loading, using different paths (VAB, LaunchPad, Resume via TrackingStation)?

I\'m asking, cause I get different behavior for my plugin enabled parts when I create a ship in VAB than if I jump straight to one already constructed on the pad.

I\'m mostly interested in:

OnPartStart

OnPartLoad

OnPartAwake

OnFlightStateLoad

I\'ve put some of my initialization code in OnPartAwake and I think that may be a bit too late...

Share this post


Link to post
Share on other sites

That\'d be handy to document. Quickest way to find out would be to put some print()s in each method, try different paths (launch game, go straight to launch pad, etc), and check the logfile for what order things happen in. I\'ve noticed some of the methods seem to get called multiple times, etc, as well, but haven\'t checked to see if that was for multiple instances of the same part, or what.

Share this post


Link to post
Share on other sites

Is it possible to process values during part.cfg reading. I tried to make them fields with custom set procedure, but it doesn\'t work - I get variable not found.

However this parser somehow processes multiple particle effects and even custom named node_stack_xxxx. Can the same mechanisms be accessed with our plugins?

Share this post


Link to post
Share on other sites

Is it possible to process values during part.cfg reading. I tried to make them fields with custom set procedure, but it doesn\'t work - I get variable not found.

However this parser somehow processes multiple particle effects and even custom named node_stack_xxxx. Can the same mechanisms be accessed with our plugins?

In my plugin, I create public String variables that can be set in the cfg. Then I do my own parsing in onPartStart. This approach gives you unspecified amount of variables, as long as they are entered in a single line in the cfg.

Share this post


Link to post
Share on other sites

What I could REALLY use is a couple of code examples of applied maths: eg, deriving compass heading/yaw, pitch and roll, and velocity vectors in m/s (handy for landing) from available vectors/quads - a 'paste this in and you\'ll find it in the double \'YourHeading1\'' job.

I know that MechJeb, for example, has such stuff in it\'s source, but separating it from the mechanics of MechJeb isn\'t easy for a c# novice (and I don\'t like to butcher others\' code without express permission!) - plus having such references in one labelled spot would also make it easier for us novices. I know I\'d appreciate it, anyway.

Y\'know, if there\'s enough maths to do on the various parameters the game creates to make them 'player useful', there could even be a call for a maths library plugin...

Share this post


Link to post
Share on other sites

You can find some example vector math here: http://kspwiki.nexisonline.net/wiki/Module_code_examples

I think I love you.

*edit*

Right, so....

//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

...

//direction in which the ship currently points:
Vector3d heading = (Vector3d)vessel.transform.up;

How would I turn that into a heading (just like the text at the bottom of the Navball, but with a tad more precision)? I figure it\'s the likely the bottom one? And in KSP, which plane is up? y or z? (Used to C4D, where y is up, but others use z)

Share this post


Link to post
Share on other sites
//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

...

//direction in which the ship currently points:
Vector3d heading = (Vector3d)vessel.transform.up;

How would I turn that into a heading (just like the text at the bottom of the Navball, but with a tad more precision)? I figure it\'s the likely the bottom one? And in KSP, which plane is up? y or z? (Used to C4D, where y is up, but others use z)

To get a heading in degrees you\'d probably do some trigonometry like

double eastComponent = Vector3d.Dot(heading, eastUnit);
double northComponent = Vector3d.Dot(heading, northUnit);
double headingRadians = Math.Atan2(eastComponent, northComponent);
double headingDegrees = headingRadians * Math.PI / 180.0;
if(headingDegrees < 0) headingDegrees += 360.0;

I haven\'t tried that code, so it might have mistakes.

I believe that in KSP\'s world coordinates, the y axis (i.e., second component of Vector3d objects) points along the rotational axis of Kerbin (also the rotational axis of the moon, and the normal vector to plane of the Kerbin system). Personally, in my code I don\'t use this fact and instead base everything off the unit vectors constructed in that example code. I basically never access, say, the x component of a vector. Instead I take dot products with appropriate unit vectors. This way I don\'t have to worry about the way KSP\'s coordinate axes are actually oriented.

Share this post


Link to post
Share on other sites

Ok, that *almost* works... the code compiled fine, but the results of HeadingDegrees are a tad odd:

From actual bearings 0 - 180, HeadingDegrees goes from approx 0.055 to 0. When it crosses the 180 line on the navball, HeadingDegrees jumps to 360. Actual heading 180 - 359 makes HeadingDegrees go from 360 to 359.945.

So it\'s going down when the actual heading goes up (easy enough to correct, just deduct from 360),

Ok, got it working! Rad to Deg is *180/pi, but you were close enough to point me the right way!

Bit of a chunk of text (though I imagine some of the other values used to derive this will be of use)


Vector3d upUnit = (position - vessel.mainBody.position).normalized;
Vector3d northUnit = Vector3d.Cross(upUnit, eastUnit); //north = up cross east
Vector3d heading2 = (Vector3d)vessel.transform.up;

double eastComponent = Vector3d.Dot(heading2, eastUnit);
double northComponent = Vector3d.Dot(heading2, northUnit);
double headingRadians = Math.Atan2(eastComponent, northComponent);
double headingDegrees = headingRadians * 180.0 / Math.PI;
headingDegrees = 180 - headingDegrees;
if (headingDegrees > 360) headingDegrees -= 360;
if (headingDegrees < 0) headingDegrees += 360.0;
      Vector3d eastUnit = vessel.mainBody.getRFrmVel(position).normalized; //uses the rotation of the body\'s frame to determine 'east'

Looking to see what I can do to reduce it :)

*edit*

Ok, the other method I found was in the MechJeb source (so clearly credit to r4m0n). No idea what MoI is though...


Vector3d CoM;
Vector3d MoI;
Vector3d up;
Quaternion rotationSurface;
Quaternion rotationVesselSurface;

CoM = vessel.findWorldCenterOfMass();
MoI = vessel.findLocalMOI(CoM);
up = (CoM - vessel.mainBody.position).normalized;

Vector3d north = Vector3.Exclude(up, (vessel.mainBody.position + vessel.mainBody.transform.up * (float)vessel.mainBody.Radius) - CoM).normalized;
rotationSurface = Quaternion.LookRotation(north, up);
rotationVesselSurface = Quaternion.Inverse(Quaternion.Euler(90, 0, 0) * Quaternion.Inverse(vessel.transform.rotation) * rotationSurface);

vesselHeading1 = rotationVesselSurface.eulerAngles.y;
      double vesselHeading1;

Many thanks for your help -= you never know, I may be back!

Share this post


Link to post
Share on other sites

To do a LineRenderer, you must attach the line to a part like this :


[name].transform.parent = transform

So can we do a part that attaches to another upon collision, like this ?


override onCollide (collide Collide)
{
[name].transform.child = transform
}

Share this post


Link to post
Share on other sites

OnPartActivate - happens when you press Spacebar and the stage with your part is activated.

OnPartAwake - I believe this is available when unpausing the game.

OnFlightStart - this happens when you click 'Launch' in the VAB and the ship is placed on the launch pad.

I\'m doing the initialization in onPartStart();

Awake according to Unity documentation.

Awake is used to initialize any variables or game state before the game starts. Awake is called only once during the lifetime of the script instance. Awake is called after all objects are initialized so you can safely speak to other objects or query them using eg. GameObject.FindWithTag. Each GameObject\'s Awake is called in a random order between objects. Because of this, you should use Awake to set up references between scripts, and use Start to pass any information back and forth. Awake is always called before any Start functions. This allows you to order initialization of scripts. Awake can not act as a coroutine.

Share this post


Link to post
Share on other sites

The onPartAwake isn\'t a standard Unity thing - it\'s exclusive to this game, so that documentation is probably wrong in this instance.

For anyone wondering, onPartLoad happens when a part is loaded at the start of the game, and this is before the part.cfg is loaded.

Share this post


Link to post
Share on other sites

This is what I\'ve discovered/been using in lieu of any real documentation for the Part class. If you compile this and set is as the module for a part, you\'ll get a debug print (show using Alt-F2) as each member function runs. Note that the commented-out ones will spam the debug console if re-enabled.

[tt]

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using UnityEngine;

public class DebugPart: Part

{

// Called when part disconnects from vessel due to crash etc. - seems to be called first

// Also called when part is lowest part of a stack above a decoupler

protected override void onDisconnect()

{

print('DBG: onDisconnect');

base.onDisconnect();

}

// Called in VAB after onPartAttach() or any update of vessel in VAB

// Also called after onPack()

public override void onBackup()

{

print('DBG: onBackup');

base.onBackup();

}

// Called in VAB when copying a part for symmetric placement

protected override void onCopy()

{

print('DBG: onCopy');

base.onCopy();

}

// Called continually when part is active anywhere in VAB, after onPartStart()

protected override void onEditorUpdate()

{

//print('DBG: onEditorUpdate');

base.onEditorUpdate();

}

// Called in VAB when removing a part after onPartDelete()

// or in flight scene when destroying a part after onPartExplode()

// also after part goes out of range (>2.5km) of focussed ship

protected override void onPartDestroy()

{

print('DBG: onPartDestroy');

base.onPartDestroy();

}

// Does not seem to be reliably called - mostly when decoupler explodes

protected override void onDecouple(float breakForce)

{

print('DBG: onDecouple(' + breakForce + ')');

base.onDecouple(breakForce);

}

// Called at beginning of flight scene after onPartStart()

// also when part comes in range of focussed ship (<2.5km) after onPartStart()

protected override void onFlightStart()

{

print('DBG: onFlightStart');

base.onFlightStart();

}

// Called for launchpad start after onFlightStart()

protected override void onFlightStartAtLaunchPad()

{

print('DBG: onFlightStartAtLaunchPad');

base.onFlightStartAtLaunchPad();

}

// Called when loading the flight state, such as when part goes off-rails

public override void onFlightStateLoad(Dictionary<string, KSPParseable> parsedData)

{

print('DBG: onFlightStateLoad');

base.onFlightStateLoad(parsedData);

}

// Called when saving from VAB and during flight state save, such as when part goes on-rails

public override void onFlightStateSave(Dictionary<string, KSPParseable> partDataCollection)

{

print('DBG: onFlightStateSave');

base.onFlightStateSave(partDataCollection);

}

// Called when any vessel control input occurs, even automatic

// may be called during part placement before flight scene is properly setup

protected override void onCtrlUpd(FlightCtrlState s)

{

//print('DBG: onCtrlUpd(' + s + ')');

base.onCtrlUpd(s);

}

// Called when game is paused (ESC)

protected override void onGamePause()

{

print('DBG: onGamePause');

base.onGamePause();

}

// Called when game in unpaused

protected override void onGameResume()

{

print('DBG: onGameResume');

base.onGameResume();

}

// Called when part soft-lands on water

protected override void onPartSplashdown()

{

print('DBG: onPartSplashdown');

}

// Called when part goes on rails (>500m from focussed ship)

protected override void onPack()

{

print('DBG: onPack');

base.onPack();

}

// Called when part goes off-rails

protected override void onUnpack()

{

print('DBG: onUnpack');

base.onUnpack();

}

// Does not seem to be called

protected override void onPartTouchdown()

{

print('DBG: onPartTouchdown');

base.onPartTouchdown();

}

// Called in VAB when deleting a part, just before onPartDestroy()

protected override void onPartDelete()

{

print('DBG: onPartDelete');

base.onPartDelete();

}

// Called in VAB when attaching to another part - 'parent' gives attached part

protected override void onPartAttach(Part parent)

{

print('DBG: onPartAttach(' + parent + ')');

base.onPartAttach(parent);

}

// called in VAB when detaching part from vessel

protected override void onPartDetach()

{

print('DBG: onPartDetach');

base.onPartDetach();

}

// Initial call in VAB when picking up part

// Also called when part comes into range of focussed ship (<2.5km)

// And at initial part loading at program start

protected override void onPartAwake()

{

print('DBG: onPartAwake');

base.onPartAwake();

}

// Called when part is deactivated after onDisconnect()

protected override void onPartDeactivate()

{

print('DBG: onPartDeactivate');

base.onPartDeactivate();

}

// Called after explosion of part due to crash etc.

// Seems to be after explosion effects are applied

protected override void onPartExplode()

{

print('DBG: onPartExplode');

base.onPartExplode();

}

// Called in VAB after onPartAwake()

// Also in flight scene on vessel placement just before onFlightStart()

// and when part comes into range of focussed ship (<2.5km)

protected override void onPartStart()

{

print('DBG: onPartStart');

base.onPartStart();

}

// Called during initial part load at start of game

protected override void onPartLoad()

{

print('DBG: onPartLoad');

base.onPartLoad();

}

// Does not seem to be called

protected override void onPartLiftOff()

{

print('DBG: onPartLiftOff');

base.onPartLiftOff();

}

// called regularly during flight scene if on focussed vessel - after each frame render?

protected override void onPartUpdate()

{

//print('DBG: onPartUpdate');

base.onPartUpdate();

}

// called continuously during flight scene if on focussed vessel

protected override void onPartFixedUpdate()

{

//print('DBG: onPartFixedUpdate');

base.onPartFixedUpdate();

}

// called regularly during flight scene if in active stage - after each frame render?

protected override void onActiveUpdate()

{

//print('DBG: onActiveUpdate');

base.onActiveUpdate();

}

// called continously during flight scene if in active stage

protected override void onActiveFixedUpdate()

{

//print('DBG: onActiveFixedUpdate');

base.onActiveFixedUpdate();

}

// called for parts connected to something else after onPack()

protected override void onJointDisable()

{

print('DBG: onJointDisable');

base.onJointDisable();

}

// called for parts connected to something else after onUnpack()

protected override void onJointReset()

{

print('DBG: onJointReset');

base.onJointReset();

}

// called when stage part is on becomes active

protected override bool onPartActivate()

{

print('DBG: onPartActivate');

return base.onPartActivate();

}

}

[/tt]

Share this post


Link to post
Share on other sites

Having some problems compiling...

No errors in my code, but this is what it says :

error CS5001: Program `/Users/barabarabouley/Projects/Harpoon/Harpoon/bin/Debug/Harpoon.exe\' does not contain a static `Main\' method suitable for an entry point

I don\'t want to compile it to an EXE, and what is that error ?? ?

I\'m using MonoDevelop on Mac OSX

Share this post


Link to post
Share on other sites

Disclaimer: I\'m not a c# expert, been coding in it for a week or so :P

But:

if it complaing about a lack of main method, it means it wants to treat your project as a standalone program - the main method is a standard entry point into such. I believe you have chosen wrong project type when you began coding - it should be c# library.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.