Jump to content

[1.8.x] KSPWheel - Physics Based Alternate Wheel Collider [API Only]


Shadowmage
 Share

Recommended Posts

3 hours ago, Shadowmage said:

Does kOS properly call (or otherwise trigger) the 'on field changed' callback when KSPFields are updated?

E.G:  https://github.com/shadowmage45/KSPWheel/blob/master/VSProject/KSPWheel/PartModules/KSPWheelBase.cs#L397

This is apparently the bit that might be causing problems.  Basically the stuff works fine when using the actual GUI controls.  But there may be problems when those same fields are updated by kOS.  (I cannot confirm any of this as I do not use kOS, and am basing this entirely on one user report that stated the functions were not updating properly)

If changing a KSPField value does not trigger the on field changed event, then the event system is designed wrong by SQUAD.

The event isn't "onFieldChangedByTheGui".  It's "onFieldChanged" period.  It *should* be implemented with this pathway:

Value might change by the gui or might change by code.

Either way, the act of changing the field triggers the onChanged event (i.e. make it a Property where the Setter checks if the new value differs from the old, and it does this event regardless of who changes the value or why they do it).

But of course that's not what happens, is it?  Because SQUAD decided to make these things be fields not properties, so they can't have setters that trigger when you change the value.  Sigh.  Damn.  Time and time again we run into these problems where KSP puts what should be low-level logic at too high a level, up in the UI (so calling an API from code skips important functionality buried in the UI code).  I've never heard of onFieldChanged for KSPFields, so no we didn't fire it off.

 

Edited by Steven Mading
Link to comment
Share on other sites

18 minutes ago, Steven Mading said:

If changing a KSPField value does not trigger the on field changed event, then the event system is designed wrong by SQUAD.

Changing the value of the field directly does not call 'onFieldChanged'.  The entire KSP BaseField system is implemented through reflection from what I can tell (where BaseField is just a convenience wrapper around some reflection function calls).  There is no way to know via reflection if a field was updated externally -- there is no built-in facility in C# for auto-callback-on-field changed. 

What happens in KSP is that the GUI code manually calls the 'onFieldChanged' callback whenever the field is changed through the UI controls, but it has no knowledge of if the field was updated externally/through code. 

Yep, been quite a PITA to work around, even just for my own purposes.  You pretty much have to have source-access to whatever modules you are trying to manipulate, just so you can know if there is any specific 'on field changed' code that needs to be run after you update any given field.  Obviously only really works for mod added modules, as those are the only time you'll have source access.

 

Yes, SQUAD should have set them up as a property of some sort, so that whenever the set method is called, it can run all the internal validation and callback routines.  Probably too late to do anything about it now (and even if they did it would break...well.. all the mods...).

 

27 minutes ago, Steven Mading said:

Time and time again we run into these problems where KSP puts what should be low-level logic at too high a level, up in the UI (so calling an API from code skips important functionality buried in the UI code).

No kidding.  Or entire systems hidden behind internal/protected/private methods and/or classes for no apparent reason.  And the complete lack of documentation/comments in the API really doesn't help things.

 

 

 

23 minutes ago, Steven Mading said:

I've never heard of onFieldChanged for KSPFields, so no we didn't fire it off.

Ahh... that would explain it :)

It should be a (relatively) simple change to also call the onFieldChanged callback for a given KSPField whenever the values are updated by kOS.  About the only tricky thing is that there are actually two callbacks; one on the uiControlEditor, one on the uiControlFlight, and the correct one needs to be called depending on the current scene.

Link to comment
Share on other sites

21 minutes ago, Shadowmage said:

Changing the value of the field directly does not call 'onFieldChanged'.  The entire KSP BaseField system is implemented through reflection from what I can tell (where BaseField is just a convenience wrapper around some reflection function calls).  There is no way to know via reflection if a field was updated externally -- there is no built-in facility in C# for auto-callback-on-field changed.

I just checked our code and it seems we only change the field by calling BaseField.SetValue(), rather than directly.

So the opportunity to trigger the event does exist if the KSP code was written for it- given that we set the value through a method call rather than directly.  If you're not seeing it happen then I don't know why, and trying to find out why would involve crossing a legal line into spying on KSP code so I can't go there.  All I know from here is that we definitely use SetValue() to do it, and other mods I searched on GitHub also use SetValue() on BaseFields all the time without explicitly having to call the onFieldChanged callback afterward (in fact so does KSPWheelBase itself in one place).  We are definitely doing pretty much the same thing the other mods are in regards to setting KSPFields.

Edited by Steven Mading
Link to comment
Share on other sites

17 minutes ago, Steven Mading said:

If you're not seeing it happen then I don't know why, and trying to find out why

Well, its not me having a problem.  I can neither confirm or deny if the fields/values are being updated.  I do not use kOS personally, and have no intentions of using it in the future (nothing against the mod; but if I'm going to write code... I have other options...)

But thanks for taking the time to investigate regardless.  I suppose if the issue persists I'll have to have the users' gather more data, or simply go to 'kOS not supported'

 

19 minutes ago, Steven Mading said:

All I know from here is that we definitely use SetValue() to do it,

Yep, that should be enough.  Pretty sure that method will call the onFieldChanged callback.  Of course, as you mention, there is no way to be sure due to lack of source access.

Link to comment
Share on other sites

  • 2 weeks later...

Hey @Shadowmagej thanks for all your hard work on the API it's really amazing.
I have just gone through a week of study and Blender/Unity acrobatics to get to the point I can ask some intellligent questions..
(BTW do people realize they can import a blend file as an asset in Unity and update it on the fly?)

Anyway, i think I could do a fresh perspective on the tutorial.I'm gonna give it a try.

Meanwhile, I have a small remaining problem.  It is lik

e my wheel has a bump it rebounds off of at each revolution.

beyond that everything seems normal.

I have only the wheel collider ias far as colliders in the model.
 

Link to comment
Share on other sites

17 hours ago, Dr_Goddard said:

Meanwhile, I have a small remaining problem.  It is lik

e my wheel has a bump it rebounds off of at each revolution.

beyond that everything seems normal.

I have only the wheel collider ias far as colliders in the model.

Would you have a model / mod download that I could look at?  (just the part .cfg and model .mu files should be sufficient)

Whatever the problem is, sounds likely to be a simple thing to cleanup on one place or another.

 

17 hours ago, Dr_Goddard said:

Anyway, i think I could do a fresh perspective on the tutorial.I'm gonna give it a try.

If you think you are up for it, would be much appreciated.  Of course, if you run into any questions, don't hesitate to ask :)

Link to comment
Share on other sites

A few questions sir.

Is it fair to say the KSPWheelComponent Unity script is not a great simulation for what will happen in game?

Is the Unity plugin very sensitive to imbedded transforms on models imported from Unity?(un-applied?)

(i got very lazy because I was able to just chuck a model into an empty game object and Bob's your uncle.

Do you just chuck things into empty game objects and manage trransforms that way,? i seemed to get a lot of very odd behaviour.

I'll post my .unity file later. But right now I think I'm damn close to getting this.
I probably need some help with suspension transforms. I'll keep you posted.

Thanks!

 

Link to comment
Share on other sites

8 minutes ago, Dr_Goddard said:

Is it fair to say the KSPWheelComponent Unity script is not a great simulation for what will happen in game?

If you've set everything up properly in the UnityEditor, that component is a very good example of how the colliders will behave in-game.  But only if you've set everything up properly.  If you don't set it up properly... well.. its either not going to work at all, or will act very strange.  See below -- there is a sample project in the KSPWheels repository that has everything setup for you.  (this applies to the wheel physics only; all of the mesh/transform manipulation stuff is entirely different between that component and the in-game uses).

Specifically, that component was intended for early debug and development of the physics model, allowing for most functions to be tested in the UnityEditor without needing to launch KSP a bunch.  It is not used by KSPWheels when actually loaded into KSP.  It really is of no use to anyone except me or someone else wanting to do low-level physics debugging.

But, to be clear, you don't actually need to add anything to your models in the Unity Editor.  Just rig them properly, and run them through PartTools.  The KSPWheel plugin code will add the necessary components and setup the wheel colliders based on the data in the part config file.

 

9 minutes ago, Dr_Goddard said:

Is the Unity plugin very sensitive to imbedded transforms on models imported from Unity?(un-applied?)

It uses whatever the transform orientations are as they appear in the Unity editor, not necessarily whatever they appear to be in your modeling program.

The only really important one is the transform used for the wheel-collider.  It must be set with Z+ = forward and Y+ = upward (Y axis = suspension actuation direction).  All other transforms have some sort of config-level specification for which axis to use.

 

37 minutes ago, Dr_Goddard said:

Do you just chuck things into empty game objects and manage trransforms that way,? i seemed to get a lot of very odd behaviour.

It depends -- are you trying to do testing/stuff in the Unity Editor, or are you trying to actually use it on a model in KSP?

Unity Editor -- check out the unity project that is in the KSPWheels repository.  It should include a fully rigged and setup vehicle and scene for testing (including some ramps and other obstacles).  https://github.com/shadowmage45/KSPWheel/tree/master/UnityProject

If using them on a model in KSP - don't add anything extra to your transforms in the Unity Editor (no KSPWheel stuff, no WheelCollider stuff).  Instead, set up the part config file properly, and the PartModules will take care of the rest.

Link to comment
Share on other sites

The suspension does wonders for the realism of movements.
Sorry about the video quality, I do all my development on an old Macbook
I need some help with the setup to use 6 wheels.
I have to add actuators to turn them in the right direction.
Will KSPWheel resolve any of the setup for multi wheels on it's own? 
 

Link to comment
Share on other sites

9 minutes ago, Dr_Goddard said:

Will KSPWheel resolve any of the setup for multi wheels on it's own? 

Define 'on its own'? and 'multi wheels'?

Yes, you can have multiple wheel colliders in a part.  No, it is not handled automatically -- you have to write the config explicitly to handle mutiple wheels.  See the track parts included in KF for some basic info on how to setup the KSPWheelBase module, or possibly a better sample might be some of the other mods using KSPWheel that have multiple integrated wheels (I can't think of any samples off the top of my head...).

In the end you will want a single KSPWheelBase module that manages all wheel colliders physics functions, and one KSPWheelMotor/KSPWheelSteering/KSPWheelSuspension/KSPWheelBrakes/KSPWheelRotation for each wheel collider that needs the corresponding function (you don't need to add steering/motor/etc modules for a wheel collider that won't use those functions).  Be warned, the in-game UI for multi-wheel-equipped parts can get bloated (though there are some special modules for helping with that, once you get that far).

Link to comment
Share on other sites

Just a bit of a walk-through of making my wheels work with KSPWheel.

I read everything I could before embarking on using KSPWheel. As you can imagine over the course of development with many-many versions and many mod devs integrating KSPWheel into wonderfully complex models, some information is deprecated. I thought a quick and straightforward walk-through using my recent wheel development as a basis would help beginners like me.

I first created my pinionWheel model in Blender and made sure to apply all transforms and rotations before dragging my .blend file into my Unity assets. This is a great way to model because you can make changes in blender on the fly and they update in Unity as soon as you save the file.

I created an empty gameObject at 0,0,0 , renamed it pinionWheel, and added partTools by clicking on add component. Then I dropped my pinionWheel model into the scene and positioned it under the pinionWheel gameObject in the hierarchy tree.

agTJpz7.png

I arranged all the parts as you see in the tree. All the objects are meshes except the wheelCollider which is an empty gameObject(i'll get to that)

The top plate is the mounting point. You can call the parts anything you want, they are identified by their name in the config file. I'll put the config file in the post at the end.

It's important the root part has a collider mesh, or you can make a separate gameObject with a collider mesh attached if you want to put the object into a layer26 [wheelColliderIgnore] to prevent interference wit the wheelCollider(wheelCollider explanation coming).

This root part also MUST have a rigidBody component.

UrzyOSE.png

This is just to show the topPlate is a mesh, not an empty transform. I had real problems with using empty transforms. @ShadowMage you seem to be telling me I shouldn't have these problems, but the example car in the UNITY scene you provide on GitHub is built like this, and it works... so cool.

9wNnI6u.png

You're gonna need a wheel. This wheel is three parts. Not necessary at all, but that's the way I rolled it this time. I found if I child the hub and axle off the tire parent it works nice.
Wheel components must share a COMMON location 0,0,0 and rotations should be 0,0,0.  The rest of the parts transforms don't really matter.
The wheel must also be positioned so Y+ is up and Z+ is forward. (The objective is to get the wheel pivot point along the X axis.

JbD0zpS.png

The Rotator is my steering axis. It is directly in line with the centre of the wheel. In the case of my model, everything pivots with steering except the topPlate. So all the parts are children of the topPlate.

vOnXJUL.png

In my model, I wanted the chainPlate to move up and down with the wheel when the suspension moves. So the wheel parts are a child of the chainplate.

AXxW9DF.png

Last but not least...
wheelCollider.
The wheelCollider is the magic component that does it all. But it's not a collider at all in UNITY. It's just an empty game object with the same origin and rotation as the wheel in your model.

Just an aside. I found the scripts @shadowmage provided for UNITY to be a bit counterproductive for me. I just couldn't get the part to function properly in the UNITY game simulation. So I spent a lot of hours messing around in UNITY when the scripts are NOT AT ALL NECESSARY to making the KSPWheel API work for you.

All you need is a properly organized gameObject hierarchy. No standard wheel colliders. No bounds box. No colliders necessary except for your non-wheel parts if you like. You must have at least ONE collider object in the model or you can't grab parts in the ship editor.

So aside from the empty wheelCollider gameObject there is NOTHING SPECIAL about any of the parts. Without the KSPWheel.dll this would be a regular static part, except it would have no collider attached to the wheel and it will sink into the ground. KSPWheel generates the actual wheel collider it uses programatically. All the setup and configuration is done in the config file.

dSE3Bci.png

PART
{

	// This is a very basic... the most basic wheel setup possible I think... KSPWheel rig
	// --- general parameters ---
	name = wheel
	module = Part
	author = Dr_Goddard

	// --- asset parameters ---
	mesh = Wheel.mu
	scale = 1
	rescaleFactor = 1
// nodes are not placed correctly yet. I wanted to look into the "new way" I've been hearing about.
	// --- node definitions ---
	// definition format is Position X, Position Y, Position Z, Up X, Up Y, Up Z, [node size], [crossfeed, def=1 i.e. true], [rigid attach, def=0 i.e. false]
	//node_stack_bottom = 0.75, 0.75, 0.0, 0.0, 0.0, 0.0, 1.0
	node_stack_top = 0.0, 0.75, 0.0, 0.0, 1.0, 0.0, 0
    node_attach = 0.0, 0.75, 0.0, 0.0, 1.0, 0.0, 0
	CenterOfBuoyancy = 0.0, 0.5, 0.0
	CenterOfDisplacement = 0.0, -0.3, 0.0
	buoyancy = 1.5
	buoyancyUseSine = False

	// --- editor parameters ---
	TechRequired = Start
	entryCost = 0
	cost = 200
	category = Ground
	subcategory = 0
	title = Wheel
    manufacturer = Squalid-State Devices
    description = You just have to be different don't you?

	// attachment rules: stack, srfAttach, allowStack, allowSrfAttach, allowCollision
	attachRules = 1,1,1,1,0



	// --- standard part parameters ---
    // --- Standard Part Parameters ---
    mass = 0.15
    dragModelType = default
    maximum_drag = 0.2
    minimum_drag = 0.2
    angularDrag = 2
    crashTolerance = 50
    maxTemp = 2000
    breakingForce = 100
    breakingTorque = 100


    	MODULE
    	{
    		name = KSPWheelBase
    		wheelColliderName = wheelCollider // remember the wheelCollider empty object at 0,0,0? This is it.
    		wheelColliderOffset = 0
    		wheelRadius = 0.4
    		wheelMass = 0.07
    		suspensionTravel = 0.15 //I saw old references to a minimum .25 for suspension travel... but it seems it was improved since
    		loadRating = 1.5
    		minLoadRating = 0.25
    		maxLoadRating = 3
    		maxSpeed = 100
    	    groundHeightOffset = 0.4 //this is your wheel ride height adjustment
            //boundsColliderName = Bounds
    	}
    	MODULE
    	{
    		name = KSPWheelRotation
    		wheelMeshName = tire //this is the tire mesh in the model. Remember, all the other spinning components (hub/axle) are children.
    		rotationAxis = 1,0,0
    	}
    	MODULE
    	{
    		name = KSPWheelSuspension
    		suspensionName = chainPlate //This is my parent suspension part. Everything that moves up/down with suspension should be                                         //a child of this
    		suspensionOffset = 0
    		suspensionAxis = 0, 1, 0
    	}
    	MODULE
    	{
    		name = KSPWheelSteering
    		steeringName = rotator //this is the parent part of components that move with steering
    		maxSteeringAngle = 30
    		steeringAxis = 0, 1, 0
    	}
    	MODULE
    	{
    		name = KSPWheelMotor
    		maxMotorTorque = 2.6
    		maxRPM = 2500
    	}
    	MODULE
    	{
    		name = KSPWheelBrakes
    		maxBrakeTorque = 12
    	}
    	//MODULE
    	//{
    	//	name = KSPWheelDamage
    	//	wheelName = wheel
    	//	bustedWheelName = bustedwheel
    	//}
    	MODULE
    	{
    		name = KSPWheelDustEffects
    	}
    	MODULE
    	{
    		name = KSPWheelSounds
    	}
    }

I hope this helps someone.

Edit: I noticed my .CFG file calls pinionWheel just "wheel".
Just imagine it says pinionWheel where is says wheel and yer good.
I needed to change it for debugging.

Edited by Dr_Goddard
Noticed a bit of confusion with model names.
Link to comment
Share on other sites

17 hours ago, ZodiusInfuser said:

Oh I think that will help me greatly! Just need to find time to actually see what in my wheels needs to change.

Hope sooo much for the long expected return of awesome robotic wheels :)

Link to comment
Share on other sites

  • 2 weeks later...
On 14/02/2018 at 7:09 PM, Dr_Goddard said:

Just a bit of a walk-through of making my wheels work with KSPWheel.

That's one IR wheel back in-game again :D

3WN5UBQ.png

Got some things to fix still, like why the IR Base piece gets recentered at the part origin, and how to turn off the KSPWheel scaling options (as there's already TweakScale configs), but your guide saved me a tonne of time! I don't suppose you know or can point me to a guide explaining how to set up multiple wheels in a single part?

Link to comment
Share on other sites

Oh, another question. I don't suppose KSPWheel (or some other mod for that matter) has a constraint module that will set the position of a game object to be at the mid-point of two other game objects (or at least the height)? The suspension setup on my Hauler wheel would benefit from this.

Link to comment
Share on other sites

2 hours ago, ZodiusInfuser said:

Got some things to fix still, like why the IR Base piece gets recentered at the part origin, and how to turn off the KSPWheel scaling options (as there's already TweakScale configs), but your guide saved me a tonne of time! I don't suppose you know or can point me to a guide explaining how to set up multiple wheels in a single part?

You'd be not supposing correctly. 
@Shadowmage made some explanations of the solution earlier in this thread. I'd be talking out my sphincter if I tried to comment without looking it up.
Good job on the wheels! Glad to help.

Link to comment
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.

 Share

×
×
  • Create New...