Jump to content
  • Advertisement
Sign in to follow this  
Stefan Fischlschweiger

C# Spaceship steering problem

Recommended Posts

Hey guys. I haven't been here for a long time. Reason being that I didn't really code in that time. Now I've returned to my project and ran into some problem.

Last time I've worked on it, I've switched my physics engine from bullet to jitter due to unresolvable problems, but there's now an issue with my steering code.

In essence, depending on what direction I'm facing relative to the initial orientation the actual change in direction differs more or less from the actual input. 

For example, I'f I turn 90 degrees left or right it becomes impossible to turn up or down.

Now, in order to make the spaceship turn, this is the code for it:

 

Within InputSystem I calculate cursor offset from the screen center and then from it a multiplier that is then used by MovementSystem:

var mouseOffsetMagnitude = Math.Abs(_mouseOffset.Length());

                    if(mouseOffsetMagnitude < 10)
                        rot.TurnMultiplier = Vector3.Zero;
                    else if (mouseOffsetMagnitude > _screenCenter.Y*0.8)
                    {
                        rot.TurnMultiplier = Vector3.Zero;
                    }
                    else
                    {
                        var multiX = _mouseOffset.X/(_screenCenter.Y*0.8);
                        var multiY = _mouseOffset.Y/(_screenCenter.Y*0.8);

                        rot.TurnMultiplier = new Vector3((float) multiY, (float) -multiX, 0);
                    }

MovementSystem takes this multiplier, which is then multiplied by the ships steering torque and a constant to get the torque vector for steering. The torque vector is also transformed by the ships orientation to ensure it's facing the correct way and then fed into Jitter to make the ship actually turn:

var torqueVector = Vector3.Transform(rot.TurnMultiplier*phys.SteeringTorque*0.00025f, body.Orientation.FromJMatrix());
            body.AddTorque(new JVector(0.0f, torqueVector.Y, -torqueVector.X)); 

Currently roll is not used, hence the 0 value in the last line.

Share this post


Link to post
Share on other sites
Advertisement

I can't be sure from the details you've provided, but your description sure sounds a heck of a lot like Gimbal Lock.

Share this post


Link to post
Share on other sites

It sounds like gimbal lock, but looking at the code I think that the high level concept of constructing a torque to apply should work like you want it to, regardless of orientation.

My initial thought is that the transform step is somehow cancelling out the resulting torque whenever orientation starts significantly differing from your starting value (which is likely Identity?).  Perhaps the torque needs to be applied in local space?  Try just removing the Vector3.Transform line and pass (rot.TurnMultiplier*phys.SteeringTorque*0.00025f) directly to AddTorque and see what happens.

Edited by Nypyren

Share this post


Link to post
Share on other sites

Update:  OK, I examined the physics engine source code and it looks like it expects torques in world space.

Looking at your code again, I'm worried about how you're manipulating the transformed vector on the AddTorque line.  The fact that you're discarding the Z component could be what's causing the gimbal lock (see below for thought experiment).  Ideally I think that your post-transformed torque vector should be passed directly to AddTorque with no further modifications, which means you should be making your tweaks before you transform it.

Thought experiment:  Torque vectors point along the axis of rotation that they would cause.  If you want to rotate the nose to the left/right (yaw), your torque vector will be along the up/down axis of your ship.  If you want to rotate the nose up/down (pitch), your torque vector will be along the ship's right/left axis.  Assuming your base orientation is X=left/right, Y=up/down, and Z=forward/backward axis, if you put your ship into a 90 degree left/right orientation, your ship's front-back will be along the X axis and your ship's left-right axis will now correspond to world space Z axis.  That means if you want to pitch up, your torque vector will need to be along the Z axis.  But since you're zeroing out the Z component when you call AddTorque, this will result in zeroing out your torque vector completely and no torque will be applied.

Edited by Nypyren

Share this post


Link to post
Share on other sites

Yes, thanks, that did the trick. I probably had it wrong in my head because earlier iterations of my movement system, both physics and non-physics based required the Z component to be zeroed out here to prevent unwanted rolling.

The vector components being out of order in the AddTorque line has a reason though. It's required so that steering input from the mouse and actual turning match up in direction

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Advertisement
  • Advertisement
  • Popular Tags

  • Similar Content

    • By RoKabium Games
      Been a bit quiet recently, but we've been busy bug fixing and tweaking things... Now we have lots more 'Particle effects' in the game, specifically here the Flamethrower and Enemy attacks!
    • By JoshuaFraser
      Hi and thanks for reading, I have an issue with this reactive crosshair script, everything works fine until I start changing the offset. Give the script a go and you will see what I mean, when I do SetOffset(0f); it doesnt always set back to the origional state, if anyone can spot a fix I'd be super appreciative!
      using System.Collections; using System.Collections.Generic; using UnityEngine; public class ReactiveCrosshair : MonoBehaviour { [SerializeField] GameObject c_limb_prefab; private float center_offset = 0f; private float current_offset = 0f; private float max_offset = .5f; private int number_of_limbs = 4; private float limb_length = .05f; private float limb_width = .005f; private List<GameObject> c_limbs = new List<GameObject>(); public void SetupCrosshair(){ for (int i = 0; i < number_of_limbs; i++) { GameObject line_go = (GameObject)Instantiate (c_limb_prefab); line_go.transform.SetParent (this.transform); Vector3 limb_pos = new Vector3 (0f,0f,0f); //line_go.transform.position = limb_pos; line_go.transform.localPosition = limb_pos; LineRenderer line = line_go.GetComponent<LineRenderer>(); line.startWidth = limb_width; line.positionCount = 2; line.SetPosition (0, line_go.transform.localPosition + new Vector3(center_offset, 0f, 0f)); line.SetPosition (1, line_go.transform.localPosition + new Vector3(center_offset + limb_length, 0f, 0f)); line.useWorldSpace = false; c_limbs.Add(line_go.gameObject); } if (c_limbs != null) { OrientLimbs (); SetOffset (0f); } } public void OrientLimbs(){ for (int i = 0; i < c_limbs.Count; i++) { float rotation_step = 360f / (float)c_limbs.Count; c_limbs [i].transform.RotateAround (c_limbs[i].transform.position, c_limbs[i].transform.forward, 90f + (rotation_step * (float)i)); } } public void SetOffset(float _current_spread){ float offset = Mathf.Lerp (0f, max_offset, _current_spread); for (int i = 0; i < number_of_limbs; i++) { if (offset > current_offset) { Vector3 pos = c_limbs [i].transform.position + (c_limbs [i].transform.TransformDirection (Vector3.right) * offset); c_limbs [i].transform.position = pos; } if (offset < current_offset) { Vector3 pos = c_limbs [i].transform.position - (c_limbs [i].transform.TransformDirection (Vector3.right) * offset); c_limbs [i].transform.position = pos; } } Debug.Log ("SetOffset() offset: " + offset.ToString () + " _current_spread: " + _current_spread.ToString() + " localPos: " + c_limbs[1].transform.localPosition); current_offset = offset; } }  
    • By Erik Nivala
      So, as the title says i am trying to figure out a good way sync all that information with other players in Unity. My problem is that i can't come up with a good solution since i am used to creating classes for everything e.g. attachments are its own class and then the weapon would save a reference to that attachment. But since you can't send custom classes over [Command] & [ClientRPC] i am a little stuck. A solution for this would be giving each attachment for a slot a unique ID and then passing the ID to other player but i feel like that is very error prone if other ppl add a new attachment or the IDs get mixed up.
      Is there a "standard" way that this is usually done that i am missing?
      I am fairly new to programming so any help is appreciated!
    • By Paul Bto
      State of the search
      I'm not looking / I'm still looking
       
      Description
      It is a third person game where you join more players to fight against bosses in the PvE style of the mmorpg, looking for online companions to help you defeat your enemy, where everyone does their respective work, such as tank, dps or heal, in groups of 5 or 10 players.
      The difference with other mmorpg is that here, since there is no open world, you will not have to go through it doing hundreds of missions and using many hours to get to the content that really interests you, which, in the case of PvE, are the dungeons and raids.
       
      Objectives of the project
      For this project we will first make a demo that will only be the boss of a 5 player dungeon.
      The first phase of this project is to release a video gameplay for crowdfunding (kickstarter maybe), so we will focus more on the visual, which could be falsified if the mechanics do not work. If the crowdfunding gives green light would be the game, which if in turn would work would be updated in the future with more dungeons and bands. The ideal would be to make a playable demo.
       
      Compensation
      If this game generates benefits outside crowdfunding, the profits will be distributed depending on the work and disbursement of each one.
       
      Technology
      Unreal. If you want to learn how to use this software with the project, you can.
       
      Required profiles
      - At the moment 2 Programmers (if has multiplayer knowledge in Unreal better).
       
      - 1 2D Artist to make the interface design and some concepts. You are going to try make interfaces like this:

      It would be ideal if you can devote at least 7 hours by week.
      It is a plus if you have experience with high level PvE content in some mmorpg.
       
      Team structure
      Pablo. Environment artist.
      Diego. Character artist.
       
      Web
      Waiting until the equipment is assembled.
       
      Contact
      pablo.barreto.jimenez@gmail.com
       
      Additional Information
      I have the GDD, it depends on the work but, I think the demo could be done in 6 months.
      Here I leave some images of what I did of the project in Unity, where basically I have been testing (The project will be done in Unreal):



       
      Desired feedback
      If you think you can give me some advice about the project, feel free to give your opinion.
       
    • By Woody Stevens
      Hi,
       
      I am looking for a TCP or HTTP networking library similar to Lidgren (UDP).
       
      This is primarily for sending game map data and potentially other large messages from Server to Client.
       
      I do want to keep Lidgren for my chat messages, player position, small fast updates etc. I especially love the flow of data and the library usage in general, so any libraries of a similar style would be excellent. Preferably something open source, free and reliable.
      I also must be able to swap between localhost and an ip address with ease, like Lidgren, as I run a server for singleplayer/mp/lan.
       
      My game maps are similar to minecraft, but it is 2d and only one Z-level, so i'm sending a jagged array of Tile object data (currently only enum TileID.Grass) down the pipe to the Client. Problem is if i'm sending a large map 1024 x 1024 tiles down the to client that's quite a lot of data, and Lidgren is relatively slow to build the writes (before the message is even sent!). It is fine when i'm using smaller maps < 512 x 512 ( xTiles * yTiles ).

      I know about chunking and will look into implementing this later, whilst taking into account the user's position in the world to only send nearby chunks.
       
      An example of my code that can be slow:
      private void WriteWorld(NetOutgoingMessage outgoing) { try { var world = WorldManager.Instance.CurrentWorld; outgoing.Write(world.XTiles); outgoing.Write(world.YTiles); for (int x = 0; x < world.XTiles; x++) { for (int y = 0; y < world.YTiles; y++) { // Write Tile obj data outgoing.Write((int)world.Tiles[x][y]); // <-------- Slow here when xTiles and yTiles are each > 512 ! } } } catch (Exception ex) { // log send error } }  
      I'd love to hear from you guys, especially if any of you have come across a similar challenge.
    • By ethancodes
      I'm working on a system for my game that will allow the player to stack pick ups in a queue. As one pick up expires, the next automatically activates. I'm having an issue though where if I pick up the first one, it activates fine, but if i pick up a second directly after it, it overrides the first one, activates the second one, and then once it has run it's course, everything goes back to normal gameplay, no first pick up. I'm not sure why this is happening. Hopefully someone can spot what I'm doing wrong in my code.
      Here is the code for the pick up manager:
      // Update is called once per frame void Update () { if (pickUpQueue.Count != 0 && !pickUpActive) { pickUpActive = true; pickUpQueue[0].ActivatePickUp(); } DeactivatePickUp(); } void DeactivatePickUp () { if (pickUpQueue.Count != 0 && pickUpActive) { Destroy (pickUpQueue [0]); pickUpQueue.RemoveAt (0); pickUpActive = false; } } And here is the PickUp:
      public override void ActivatePickUp () { ball.GetComponent<Ball>().Speed = 2.0f; //increase ball speed... ball.GetComponent<Ball>().StartCoroutine(timer); //...set time that power up is active }  
      There is also a Base Pick Up:
      public void OnCollisionEnter2D (Collision2D collision) { Vector2 tweak = new Vector2 (Random.Range(0f, 0.2f),Random.Range(0f, 0.2f)); this.gameObject.GetComponent<Rigidbody2D>().velocity += tweak; //if the pickup makes contact with the paddle or ball.... if (collision.gameObject.tag == "Paddle" || collision.gameObject.tag == "Ball") { GameObject.FindObjectOfType<GameManager>().GetComponent<PickUpManager>().pickUpQueue.Add(this); Destroy(gameObject); //...and finally destroy power up object } } As a side note, I am trying to find a solution to this that will work for all of my pickups. Some pickups are ammo based, some are timed. 
    • By Hellados
      Hello guys, my name is Giorgi and i'm newbie game developer i'm learning Pixel art and after pixel art  i want learn C# and don't know how and where start i'm bad with programming language and know only HTML/CSS
    • By D34DPOOL
      Edit Your Profile D34DPOOL 0 Threads 0 Updates 0 Messages Network Mod DB GameFront Sign Out Add jobEdit jobDeleteC# Programmer for a Unity FPS at Anywhere   Programmers located Anywhere.
      Posted by D34DPOOL on May 20th, 2018
      Hello, my name is Mason, and I've been working on a Quake style arena shooter about destroying boxes on and off for about a year now. I have a proof of concept with all of the basic features, but as an artist with little programming skill I've reached the end of my abilities as a programmer haha. I need someone to help fix bugs, optomize code, and to implent new features into the game. As a programmer you will have creative freedom to suggest new features and modes to add into the game if you choose to, I'm usually very open to suggestions :).
      What is required:
      Skill using C#
      Experience with Unity
      Experience using UNET (since it is a multiplayer game), or the effort and ability to learn it
      Compensation:
      Since the game currently has no funding, we can split whatever revenue the game makes in the future. However if you would perfer I can create 2D and/or 3D assets for whatever you need in return for your time and work.
      It's a very open and chill enviornment, where you'll have relative creative freedom. I hope you are interested in joining the team, and have a good day!
       
      To apply email me at mangemason@yahoo.com
  • Advertisement
  • Popular Now

  • Forum Statistics

    • Total Topics
      631383
    • Total Posts
      2999687
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!