Unity general questions

Comments

  • edited
    While @dislekcia's totally right above, it sounds like we're dealing with a 2D game here, where the benefits of quaternions and their lack of susceptibility to gimbal lock is not a necessary or required property, then I don't think there's anything wrong with thinking in angles of rotation around your camera forward axis, especially not if it makes everything easier to understand. So with that, I don't see anything particular wrong with using Quaternion.Euler, and it's likely a cause for fewer errors than having to think in terms of maths you don't understand.

    That aside, they really aren't that complicated, no! They are basically a point on a 4d sphere, which is a way to represent a rotation between two directions in a similar way to how a matrix can represent a transformation.

    The issue you're having could be down to a number of factors, including a confusion between which vectors you should be using. Previewing these in the unity editor is useful, and remember the differences between local and world space/rotation (red is the x axis, green is y, blue is z. rgb=xyz). If you're rotating things around their forward axis, you're changing the direction their up and right axes will face. The default rotation of your sprite represents how exactly you need to get a thing to face the correct direction. I strongly recommend you have your prefabs/sprites oriented either that they point towards your up axis, or your forward axis, just for ease of use. Forward is preferable for 3D games, but it can unnecessarily complicate things in 2D, in which case you might prefer up.
    Thanked by 2AngryMoose mattbenic
  • hi guys

    Ive been using gamemaker for a while and i want to know when must i use unity because still dont understand whats going on in unity
  • I worked only in gamemaker for about a year, my first real dive into Unity was around April last year during Ludum Dare.

    When should you move to Unity?
    When you understand gamemaker enough to know that there's something you want to do that you can't do in gamemaker.

    Tools are only tools. Use whatever you like and are comfortable with. There are MANY people who make games commercially with gamemaker exclusively - there's no reason to abandon it if you don't feel that you need to.
    Thanked by 1mattbenic
  • Hey guys....... I have no knowledge of coding at all, and I have no 3d studio.... How can I make a first person shooter with unity?.......Maybe some coding tutotials?
  • @Mike16y check out www.cooking with unity.com they have a physics puzzler series (fps style like portal) as well as a FPS series of tutorials. All art is done in unity and he explains the code somewhat as he works through it.
  • Hi Guys,

    Need some help with a silly problem. I have a round gameobject (2d sprite of a planet). I currently have 2 BoxCollider2Ds attached to it. One to the top half and One to the bottom half. They are set up as triggers. When the player enters the trigger's they affect the gravity of the player. The top one pulling the player down, and the other pushing the player up. I got this working the way I want...sort of...well I would prefer if I had 2 CircleCorllider2Ds..or half circles. Any ideas. Here is a pic to better explain what I want:

    image
  • I'm guessing this is the closest you'll get to that:

    http://docs.unity3d.com/ScriptReference/PolygonCollider2D.html

    Do you actually need them to be circular? Would the two boxes not be good enough?

    I don't think there are half circles in colliderland.

    Alternatively, you can detect distance from the centre to any object, then decide if it's above or below simply enough with just the y co-cordinate.
    Thanked by 3FanieG garethf Chippit
  • @Tuism thanks for the prompt response. YES!!!! I can edit the Polygon one to suit my needs. Knew I was missing some obivious solution. Just also saw effectors too. Guess that could be another solution.
  • Hey guys

    I'm making a series of Unity stuff that will open each other, so call them A, B and C.

    For example:
    Player is in A, and presses [3], it'll open C.
    Player is in A, and presses [2], it'll open B.
    Player is in A, and presses [1], it won't do anything.

    I'm using this code to open stuff (in Windows). This opens a file that's in the same folder as the original game.

    Process process = new Process();
    		process.StartInfo.FileName = Application.dataPath + "/../" + "1pgame.exe";
    		process.Start();
    		process.WaitForExit();


    The question I have is - when I make A open B and make B open A again, it launches a separate instance of the game, and since the original game doesn't close, you end up with duplicate instances of games.

    How do you:
    1. Close the current game then launch another game, so that there won't ever be more than one thing running at a time? Or
    2. How do you make it more like an alt-tab to a different game rather than open another instance of the game? (I've checked out Force Single Instance in build options, but it seems to only make any subsequent launches fail, instead of giving the old game focus and switching to it. Or
    3. Any other ideas?

    Richard wrote the wrapper for the AMAZE little mini arcade that ran their bunch of games, which gave me this idea. Not sure if they had this same problem though.
  • edited
    Really not my speciality, but this is what my Google-fu returned:
    http://stackoverflow.com/questions/7357675/how-can-i-set-the-focus-to-application-which-is-allready-in-running-state

    [DllImport("user32.dll")]
    internal static extern IntPtr SetForegroundWindow(IntPtr hWnd);
    
    [DllImport("user32.dll")]
    internal static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
    ... 
    Process currentProcess = Process.GetCurrentProcess();
    IntPtr hWnd = currentProcess.MainWindowHandle;
    if (hWnd != IntPtr.Zero)
    {
        SetForegroundWindow(hWnd);
        ShowWindow(hWnd, User32.SW_MAXIMIZE);
    }
    Thanked by 1Tuism
  • Thanks @Elyaradine, I tried to understand that but failed :P

    I did however work out a janky solution, I start the new game and immediately quit the current one, and that way there are never old processes lying around.

    Process process = new Process();
    		process.StartInfo.FileName = Application.dataPath + "/../" + "1pgame.exe";
    		process.Start();
    		Application.Quit()


    Seems to work :D
  • General questions strikes back :p

    I have a weird one, or at least I find it weird, dunno where to look...

    I'm using a struct to define a PlayerObject, then passing one of the PlayerObjects into a function. In the function, I can't seem to refer to the PlayerObject and make changes to its functions, but I can refer to an instance of the PlayerObject and change it directly... What am I doing wrong?

    Relevant code:

    public struct PlayerObject
    {
    	public int state;
    }
    
    public class GameController : MonoBehaviour 
    {
    	public PlayerObject P1;
    	
    	etc etc
    
    	void MoveBlocks (PlayerObject _player, Vector2 _direction)
    	{
    		_player.state += 1; // this line doesn't work
    		P1.state += 1; //this line works
    	}
    }


    Of the two lines there in the MoveBlocks function, the first doesn't work, no errors, nothing. The second line works, but I want to pass different PlayerObjects into the function so that it's not always the same PlayerObject.

    What am I missing?
  • Okay I found the answer to my question - according to a Unity answer:
    You cannot modify the values inside a struct returned from another component the way you are - and for good reason. A struct is passed by value.
    http://answers.unity3d.com/questions/425510/cant-modify-struct-variables-c.html

    The way to solve it is to change the struct to a class.
  • Have you tried passing the struct by reference?
    void MoveBlocks (ref PlayerObject _player, Vector2 _direction)
  • critic said:
    Have you tried passing the struct by reference?
    void MoveBlocks (ref PlayerObject _player, Vector2 _direction)
    No, what is this voodoo magic? :)

    Is there any reason to use this rather than changing the struct to a class?
  • edited
    HALP!

    I have an object that arbitrarily moves around a spherical world, and I have a camera that orbits it by moving the mouse left and right. So far so good.

    I want to get the forward vector relative to the object (whose up is always the zero point) and the ground plane (which is a 3D sphere).

    I've tried Vector3.ProjectOnPlane(Vector3 vector, Vector3 planeNormal), where vector is the camera's eulerAngles and planeNormal is playerobject.transform.position - vector3.zero... But this produces weird results. Am I on the right track or is it something else completely?

    Theoretically it's a 90 degree from the zero point to the player object, and then from the camera to the player, then forward along the "ground plane".

    Thanks for assisting!

    (I'm looking for the red vector)

    image
    Screen Shot 2017-02-16 at 7.45.35 PM.png
    568 x 525 - 27K
  • Transform itself has a .forward component and others like up, down...
  • My first thought was the same as critc's, so +1 to that. But maybe that's not what you are actually after? If so maybe posting a screenshot might help, as from the 2D image it is a bit hard to fully understand your current scenario aside from the aforementioned solution.
  • If you need to "bend" that forward vector around the sphere, something I've done in the past (it was actually used on the Broforce world map), was to take that transform.forward vector, normalize it, and multiply that by your sphere's radius+object's height above ground. That may or may not work well depending on what you're actually trying to do. <_<
  • No my ship isn't pointing forward, the camera is orbiting the ship, and I want to point the ship away from the camera, but parallel to the floor - not exactly the same direction as the camera....

    Let me try and show this visually...

    In this image you see the setup - the sphere is interior, the ship is inside the sphere, gravity "outwards", attached to the wall of the sphere, and the camera's up is towards the centre of the sphere. So far so good.

    image

    But I can't figure out how to get a forward on the ship - I seemed to have hacked together a way for it to always face away from the ship, but I want an actual vector - and I should be able to get it from the player ship object, but it just isn't. I don't know why...

    In this image you see the blue debug ray. It is this:
    Debug.DrawRay(PlayerObject.transform.position, PlayerObject.transform.eulerAngles*10f, Color.blue);

    Where PlayerObject is that ship object. No mistake. This should make it shoot a ray forward, correct? Well it doesn't, and it even doesn't follow the ship's rotation when I turn the camera.

    image

    image

    So what I'm looking to do is to get the ship to treat the inside of the sphere as any normal floor, and I want a forward that's "parallel" to the ship and its floor, aimed by the camera's facing towards the ship. Hopefully this makes more sense?

    Thanks again for looking!!!
    Screen Shot 2017-02-17 at 1.28.45 AM.png
    509 x 660 - 216K
    Screen Shot 2017-02-17 at 1.30.28 AM.png
    505 x 347 - 69K
    ship_rotate2.gif
    465 x 664 - 801K
  • Debug.DrawRay(PlayerObject.transform.position, PlayerObject.transform.eulerAngles*10f, Color.blue);

    doesn't do what you think it does. The direction should be given as a direction in world space, not in terms of Euler angles.

    Debug.DrawRay(transform.position, transform.forward, Color.blue);

    gives you a vector pointing in the direction the transform is facing (whatever it is you do with it; I'm a bit too tired to think through that).
    Thanked by 1Tuism
  • @Elyaradine THANKS FOR THAT CORRECTION! :D

    Okay so now that I have the ship's forward, I am realising that I need more than that :/

    I want to have the ship face away from the camera, but along the "ground plane" and not the literal forward of the camera. I found ProjectOnPlane which I assume takes a 3D vector and returns a 2D vector, but it's not working, am I overlooking some angle thing again? :/

    PlayerObject.transform.eulerAngles = Vector3.ProjectOnPlane(Camera.main.transform.forward, (Vector3.zero - PlayerObject.transform.position));

    Where Vector3.zero is the centre of the sphere...

    Thanks again guysssss
  • Try taking a cross product of (ground-ship) and (camera-ship) positions, it should give you the left/right vector that is parallel to the floor (I hope).
  • @critic Thanks, sp crossing those gets a left/right, then I need to turn it 90 degrees again to get a forward? Isn't there an easier and more direct way?
  • If you need to "bend" that forward vector around the sphere, something I've done in the past (it was actually used on the Broforce world map), was to take that transform.forward vector, normalize it, and multiply that by your sphere's radius+object's height above ground. That may or may not work well depending on what you're actually trying to do. <_<
    Have you tried this?
  • edited
    Tuism said:
    @critic Thanks, sp crossing those gets a left/right, then I need to turn it 90 degrees again to get a forward? Isn't there an easier and more direct way?
    You could take another cross product from (ground-ship) and that new vector, or rotate your model by 90 degrees from the beginning.
  • edited
    If you need to "bend" that forward vector around the sphere, something I've done in the past (it was actually used on the Broforce world map), was to take that transform.forward vector, normalize it, and multiply that by your sphere's radius+object's height above ground. That may or may not work well depending on what you're actually trying to do. <_<
    Have you tried this?
    I'm actually not sure what the maths here does :/ I don't think it's what I needed to do... Mostly probably because my explanation is difficult to understand XD

    @critic I want to try and keep calculations down so it doesn't confuse my already-confused head :/

    Somehow I've actually gotten it to work through a system of nested gameObjects, here's a summary of my system:
    1. The player object's up is pulled towards and away from the zero point of the sphere, thanks to @EvanGreenwood's tech :)
    2. Rotate the player left and right with Input.GetAxis("Mouse X")
    3. Camera's container LookAt() at player object, up is sphere's zero.

    --------------------------------

    Now I have a new problem - I want the player object to hover above the "ground" without touching it, and doing it with AddForce is giving me a rubber band effect of either WAY too much force or WAY too little force. I can't actually just constrain or set a Y height because the environment is spherical.... Is there a way to take distance from centre and just pull the object towards it?

    This is what I got right now that gives me mad bouncy mothion:

    Vector3 vectorUp = (Vector3.zero-PlayerObject.position).normalized;
    
    float distFromCore = (Vector3.zero - PlayerObject.transform.position).magnitude;
    
    if (distFromCore > 90)
    {
    	PlayerObject.AddForce(vectorUp * (100f - distFromCore) * 70f);
    }
  • edited
    @Tuism I think you would want to raycast to the ground so that you know how far you are currently above ground. I guess you could use the distance from core, but what if (for example) your player jumps/walks over a cliff and now his distance from the core is not at max but he is actually not on the ground anymore. So he should be pushed, however it might all make sense in your project in how it works.

    The main thing is I don't think you need the if distFromCore > 90, unless that is for some other interaction. You need to however calculate how far your space ship is from where you want it, percentage wise, decide on a force you will use to get it to where it should be and multiply that by the percentage value that it is off.

    This one uses the raycast way
    public float hoverHeight=1f; //Whatever is needed
    public float hoverForce=1f; //Whatever is needed
    
    Ray ray = new Ray(transform.position, -transform.up);
    RaycastHit groundHit;
    
    if (Physics.Raycast(ray, out groundHit, hoverHeight))
    {
          float relativeHeight = (hoverHeight - groundHit.distance) / hoverHeight; 
          Vector3 appliedHoverForce = Vector3.up * relativeHeight * hoverForce;
          PlayerObject.AddForce(appliedHoverForce, ForceMode.Acceleration);
    }


    This one uses the distFromCore
    I just zeroed my player's x,z values to get a more accurate distFromCore since i was testing this on a flat plane, and all that matters then is the Y Value
    public float hoverHeight=1f; //Whatever is needed
    public float hoverForce=1f; //Whatever is needed
    
    Vector3 zeroedPlayerPos = transform.position;
    zeroedPlayerPos.x = 0;
    zeroedPlayerPos.z = 0;
    
    float distFromCore = (Vector3.zero - zeroedPlayerPos).magnitude;
    
    float relativeHeight = (hoverHeight - distFromCore) / hoverHeight;
    Vector3 appliedHoverForce = Vector3.up * relativeHeight * hoverForce;
    PlayerObject.AddForce(appliedHoverForce, ForceMode.Acceleration);


    Also I used Vector3.up for the force directions where you would want to use PlayerObject's Up vector or if that's not accurate the one you calculated vectorUp. The same for the raytrace, fire it using your vector if needs be.

    You will need to set the hoverForce and height variables to what you need.
  • If this is still too bumpy, and you want to use AddForce, a PID should work, that way the add force will be adjusted so that the value of the force will keep it hovering at just the right height(That you set) However that is from engineering systems so won't be low on the calculations side. But here's what that looks like irl:

    And overall you could just get a PID class/script and plug in your values and go for it. I have a few links to some good Unity examples but you should be able to find them with a google search.
  • Oh I think I did a PID a while ago. Copy pasted a bunch of code and tweaked. Man I was hoping there was a simpler way than PID because everytime I engage with mad code like that I have to re-understand everything :/

    Thanks for the reminder! If you have (easy to understand :P) links please let me know :)
  • edited
    Did you see my post before I posted the PID suggestion? Or did that not work?

    Anyhoo for PID's:
    Take a look at the third post from Brian-Stone on this link or andeee's implementation here.

    Both of them are implemented in Unity and provide either an example project or asset bundle. Brian-Stone explains in his post what a PID is quite well, and although it get's a little daunting, it is nothing compared to the wiki page on PID's linked in andeee's post. Also you don't necessarily have to understand how it all works, simply use the class, pass in you values and use the default P,I and D values given in the example. Then look at the Manual Tuning Table on the wiki page to get an idea on what value to tweak if you are overshooting etc.

    One note, I believe Brian-Stone's example has a few errors in that unity changed the api from rigidbody.whatever to GetComponent<Rigidbody>().whatever so you will need to make those changes, but it will only take a few seconds.

    Lastly, Brian's PID Class takes in only two arguments, and the other takes 3. The difference being in brian's you will pass in your error value only(IE I am 0.5m from where I want to be) and the other you pass in your current height and destination height.(IE I am at 1.5m I want to be at 1m) So overall both will then do the same. The one just makes the subtraction inside the method the other you calculate it yourself.
    Thanked by 1FanieG
  • @vince yeah I tried your code and plugged in my values... And I'm not sure if I was messing things up but it didn't work at all, the object fell to the sphere wall like a stone, or it would drift. I tweaked the values a bunch and couldn't get it to cooperate.

    I actually ended up looking at the same PID class you linked, I'm not sure how exactly to implement yet given my variables are a bit more complex, (mostly given I don't actually have a target object, just a target value, and up/down is not a consistent axis but towards/away from the centre) but I'll give it another shot :)
  • edited
    Ah okay. I tested it on a flat plane so maybe it doesn't/won't work in a spherical environment.

    To use the PID, it does not really care or know what it is doing, it just takes two(or one) float and spits out the return value.

    So you would calculate your current height from the floor every frame, and pass the PID that and the height that you want to be above the floor (Which I am assuming will stay constant). So lets say for this frame you calculated your current height is 0.8f and your target is 1f, you pass those and your PID will return a float, the size of which will depend on your P,I and D values. You then use the returned value as your AddForce amount.

    To actually make the PID work you need to set the P,I and D values correctly, this usually works quite well for me (From the PID Wiki linked above):
    One tuning method is to first set Ki and Kd values to zero.

    Increase the Kp until the output of the loop oscillates, then the Kp should be set to approximately half of that value for a "quarter amplitude decay"(Read: Settles quickly) type response.

    Then increase Ki until any offset is corrected in sufficient time for the process. However, too much Ki will cause instability.

    Finally, increase Kd, if required, until the loop is acceptably quick to reach its reference after a load disturbance. However, too much Kd will cause excessive response and overshoot.
    Also as stated above, sometimes a Kd of zero works perfectly fine, and I often use them like this. The Table in that link is also very useful for adjusting your values to work.
    Thanked by 1Tuism
  • Thanks so much! So I tried the class and I've been wondering what the error was in there that you said need editing? And I noticed that if I set the D value to anything but 0 it would completely bug out... So... Dunno?
  • edited
    It was a few syntax errors, so it will give you the lines where the errors are. (This is in Brian's class implementation, not the PID class itself if i recall correctly) So it was small things like changing rigidbody to the new GetComponent<Rigidbody>() etc.

    I'd be more than happy to try take a look at it all in your scene if you could/are allowed to share it, as I'd like to take a look at how you are doing the spherical world, since I've always wondered.
  • @vince file attached! It's my pleasure to share this hack :P I've got the example scene in there and I'm not sure if the script can be implemented in my code with just substituting what's in the editor... I think.
    zip
    zip
    Insphere.zip
    12M
  • Hey. Played around with both the first suggestion and the PID, heres the file

    Hopefully that gives you something to work with. One problem is accelerating forward seems to add additional downward force to the player object, causing it to dive, and the PID can't respond quick enough. But it is indeed working. Let me know if you have any problems.

    P.S. I implemented it all in the CustomGravity script as my Visual Studio was downloading other packages, and mono was giving trouble, and didn't pick up the other files in the solution, so had no reference to the PID Class; and so I just copied the PID class over in to there and renamed it. You'll know when you see it. Just know I did everything in CustomGravity since all my tools were broken :/
  • @vince mmmm, which version of Unity did you save this file with? It's giving me errors :/
  • edited
    Ah dangit, the newest beta release :P

    Here's the code:
    using UnityEngine;
    using System.Collections;
    
    public class CustomGravity : MonoBehaviour {
    
    	public Rigidbody _rigidBody;
    	public mPID myPID;
    
    	public bool UsePid;
    	//Used by the Non-PID Mode
    	public float hoverForce;
    	//Target Height Above floor
     	public float hoverHeight;
    	//Current DistanceFromFloor
    	public float distFromFloor;
    
    
    	// Use this for initialization
    
    	void Awake ()
    	{
    		_rigidBody = GetComponent<Rigidbody>();
    	}
    
    	void Start () 
    	{
    	
    	}
    
    	void FixedUpdate ()
    	{
    		//GetPlayerPos
    		Vector3 PlayerPos = _rigidBody.transform.position;
    
    		//Calculates Distance from floor/ this might need to change to a raycast to cater for different floor heights
    		//100 = radius of world
    		distFromFloor = 100 -(Vector3.zero - PlayerPos).magnitude;
    
    
    		if (UsePid) {
    			#region PIDBasedHover
    			//Calculate base vlaue with PID, multiplied by Up vector
    			Vector3 PIDHoverForce = myPID.Update (hoverHeight, distFromFloor, UnityEngine.Time.fixedDeltaTime) * _rigidBody.transform.up;
    			_rigidBody.AddForce (PIDHoverForce, ForceMode.Acceleration);
    			#endregion
    		}
    		{
    			#region NonPIDBasedHover
    			float relativeHeight = (hoverHeight - distFromFloor) / hoverHeight;
    			Vector3 appliedHoverForce = _rigidBody.transform.up * relativeHeight * hoverForce;
    			_rigidBody.AddForce(appliedHoverForce, ForceMode.Acceleration);
    			#endregion
    		}
    
    //Sperical Gravity
    		_rigidBody.AddForce(-(Vector3.zero - _rigidBody.transform.position).normalized*90f);
    	}
    	
    	// Update is called once per frame
    	void Update () {
    	
    	}
    }
    
    [System.Serializable]
    public class mPID {
    	public float pFactor, iFactor, dFactor;
    
    	public float integral;
    	public float lastError;
    
    
    	public mPID(float pFactor, float iFactor, float dFactor) {
    		this.pFactor = pFactor;
    		this.iFactor = iFactor;
    		this.dFactor = dFactor;
    	}
    
    
    	public float Update(float setpoint, float actual, float timeFrame) {
    		float present = setpoint - actual;
    		integral += present * timeFrame;
    		float deriv = (present - lastError) / timeFrame;
    		lastError = present;
    		return present * pFactor + integral * iFactor + deriv * dFactor;
    	}
    }


    Public Settings:
    PFactor : 10
    IFactor : 0.9
    DFactor: 6
    Hover Force: 300
    HoverHeight: Whatever you need, around 5 seems good
    Thanked by 1Tuism
Sign In or Register to comment.