i use the slider to change the joint angle, here is my code.
void Update()
{
a = sliderx.GetComponent<slider>().value;
b = slidery.GetComponent<slider>().value;
headjoint.transform.Rotate(a, b, 0);
}
and after I slide the bar, the joint rotates around and won't stop. like
a += value
and not
a = value
, the slider not give a definite number?
why? do I need to use eularangle?
when I use
headjoint.transform.rotation = Quaternion.Euler(a, b, 0);
it's change the rotation angle of my object ,to 0,0,0 when running
anyideas?
Rotate as the name suggests rotates the object about a given amount. If you call this constantly with the same value your object is rotated constantly about the same amount.
You rather want to set a rotation.
Your attempt
headjoint.transform.rotation = Quaternion.Euler(sliderX.value, sliderY.value, 0);
is actually close, yes. But by default Rotate is applied in local space. So if you want that same behavior you'd rather use
// First of all use the correct type and don't use GetComponent repeatedly
public Slider sliderX;
public Slider sliderY;
void Update()
{
headjoint.transform.localRotation = Quaternion.Euler(sliderX.value, sliderY.value, 0);
}
Related
so this is what happens when Im using vector 3 on my game I want my vector 3 to be on specific position for different screen sizes? is that possible? here is my codes
public virtual void ShuffleButton()
{
Vector3 buttonFirst = gameButtons[0].transform.position;
buttonFirst.x += 297f;
gameButtons[0].transform.position = buttonFirst;
Vector3 buttonSecond = gameButtons[1].transform.position;
buttonSecond.x -= 74.25f;
gameButtons[1].transform.position = buttonSecond;
Vector3 buttonThird = gameButtons[2].transform.position;
buttonThird.x += 74.25f;
gameButtons[2].transform.position = buttonThird;
Vector3 buttonFourth = gameButtons[3].transform.position;
buttonFourth.x -= 148.5f;
gameButtons[3].transform.position = buttonFourth;
Vector3 buttonFifth = gameButtons[4].transform.position;
buttonFifth.x -= 148.5f;
gameButtons[4].transform.position = buttonFifth;
}
You are looking for the position conversion functions like Camera.ScreenToWorldPoint(). These can be found in the Unity Camera class documentation here: https://docs.unity3d.com/ScriptReference/Camera.html
If, for example, you want to place a Sprite in the top-left corner, regardless of screen size, you would use the screen or viewport space. The position of the sprite will have to be translated from this screen/viewport space to world space. You could use Camera.ScreenToWorldPoint() for this.
However, Unity uses three viewspaces: Screen, World and Viewport. You should read up on all three as your problem stems from the fact that you are trying to use world coordinates (transform.position) to set the position of UI elements (which use either the screen or world space; this is dependent on the parent Canvas settings)
I want to get a GameObject's height. I have tried with:
this.GetComponent<MeshRenderer>().bounds.size.y
But the problem with bounds is that it works with static objects only. When you have a moving object and if the rotation of the object is not perfectly aligned, the bounds (height) is not accurate anymore because it returns the height of the bounds that is a square and if you tilt an object like a plate you get the bounds height which is not accurate to the height of the object.
It is an Axis-Aligned Bounding Box (also known as an "AABB").
Please check the image I attached, there you can see the problem with moving objects and if you rotate them how the height is not accurate anymore.
Did anyone else have this kind of problem?
Any advice on how to get the object's height accurately?
One option is to use the Game Object's Collider.
You can relatively easily find the height and width of a collider so this is one way you can measure the dimensions of a game object. The collider, for example a box collider on the game object, will have to fully encompasses the object. You can do this be resizing the collider until it snugly wraps around your game object. Then when you want to find a certain dimension of the object instead find that dimension on the collider and multiply by the Game Object's transform.scale.
Here are some examples I have tested.
Example 1:
CapsuleCollider m_Collider = GetComponent<CapsuleCollider>();
var height = m_Collider.height * transform.localScale.y;
https://docs.unity3d.com/ScriptReference/CapsuleCollider-height.html
or
Example 2:
BoxCollider m_Collider = GetComponent<BoxCollider>();
var height = m_Collider.size.y * transform.localScale.y;
var width = m_Collider.size.x * transform.localScale.x;
var breadth = m_Collider.size.z * transform.localScale.z;
https://docs.unity3d.com/ScriptReference/BoxCollider-size.html
Hopefully one of these will work for you.
If not, then a second inconvenient way you can find the height is to create 2 proxy objects as children at the top and bottom of your object. Afterwards find the scalar distance between them.
Solution 1: Use Mesh.bounds
You can get the height using Mesh.bounds. Unlike MeshRenderer.bounds (or Renderer.bounds), this is the axis-aligned bounding box of the mesh in its local space (i.e. not affected by the transform).
You still need to account for the scale of the GameObject using transform.lossyScale, as follows:
public class Example : MonoBehaviour
{
private Mesh _mesh;
private void Awake()
{
_mesh = GetComponent<MeshFilter>().mesh;
}
private void Update()
{
float height = _mesh.bounds.size.y * transform.lossyScale.y;
Debug.Log(height);
}
}
(Note when using transform.lossyScale, the value can be slightly inaccurate. This is something to note if you need extreme accuracy. See the documentation on transform.lossyScale:)
Please note that if you have a parent transform with scale and a child
that is arbitrarily rotated, the scale will be skewed. Thus scale can
not be represented correctly in a 3 component vector but only a 3x3
matrix. Such a representation is quite inconvenient to work with
however. lossyScale is a convenience property that attempts to match
the actual world scale as much as it can. If your objects are not
skewed the value will be completely correct and most likely the value
will not be very different if it contains skew too.
Solution 2 (Workaround): Cache the unrotated MeshRenderer bounds
Alternatively, if in your context you are able to instantiate the GameObject without a rotation and you only need to rotate the GameObject after initialization, one workaround solution is to cache the bounds from MeshRenderer in the Awake method, as follows:
public class Example : MonoBehaviour
{
private Bounds _initialUnrotatedBounds;
private void Awake()
{
InitializeUnrotatedBounds();
}
private void InitializeUnrotatedBounds()
{
Assert.IsTrue(transform.rotation == Quaternion.identity);
_initialUnrotatedBounds = GetComponent<MeshRenderer>().bounds;
}
private void Update()
{
// Use the cached bounds. Now, even for moving objects,
// it doesn't matter if the rotation changes
float height = _initialUnrotatedBounds.size.y;
Debug.Log(height);
}
}
I have a "Lift". While being in the game, you walk into the particle system and get moved up in the air (on y).
So the particle system is a child of the cube / the lift. So when scaling the cube, I don't want to change the settings of the particle system. It should scale itself on its own.
When the cube got the y position on 5 and a height / scaling on y of 10, the particle system should place itself down at the bottom.
As you can see, I want it being full automatic.
So, when heading into the code I got this
[SerializeField]
ParticleSystem liftParticles;
private void Start()
{
Vector3 objectScale = transform.localScale; // cube scaling
Vector3 particlePos = liftParticles.transform.position; // temp position
particlePos.y = (particlePos.y - objectScale.y) / 2; // move down on y
liftParticles.transform.position = particlePos; // set particle position
float transformScalingX = objectScale.x; // x scaling of the cube
float transformScalingZ = objectScale.z; // z scaling of the cube
var shape = liftParticles.shape; // set the cone radius now
shape.radius = transformScalingX > transformScalingZ ? transformScalingX : transformScalingZ;
liftParticles.shape = shape;
}
I want to go with the following example as mentioned above..
The cube got a scaling of (3,10,3) and its position is (0,5,0)
my current calculation particlePos.y returns a value of -0,75 but it has to be -0,5.
So do I have an error in my code? (yes obviously I do ...)
The second problem is, how do I change the radius of the particlesystem? When trying to reference the radius of the cone, it says I can't change it, it is readonly.
Is it? I hope I can change this somehow ...
Edit:
Obviously, the particlesystem just has to be always on -0,5f on y when having a scaling of (1,1,1). No need for a calculation anymore.
But I still need to change the radius of the shape and set the lifetime of the particles relative to the height of the lift. Means
private void Start()
{
Vector3 liftScale = transform.localScale; // Liftscaling
var shape = liftParticles.shape; // temp shape
shape.radius = liftScale.x > liftScale.z ? liftScale.x : liftScale.z; // set radius
liftParticles.shape = shape; // assign the temp shape to the real shape
liftParticles.main.startLifetime = ; // set the liftetime of the particles relative to its parent height on y
}
As I understand you made the particle system child of the lift (a cube) so it can move together. In case you just want that both of them move together, but they scale independently, you should consider to use an Empty GameObject as a parent.
You can placed this Empty GameObject in the middle of the Cube (your lift) and then make the lift and the particle filter children of that Empty GameObject. Then move the Empty GameObject instead of the lift, and the children will move as well.
About modifying the radio, try this script
GameObject myParticleGenerator;
ParticleSystem.ShapeModule pShape;
pShape = yParticleGenerator.GetComponent<ParticleSystem>().shape;
pShape.radius = 4.0f;
I have stuck in this simple problem but unable to understand that why i am unable to control it.
I have these line of code which is displaying my canvas object in front of my player(camRotationToWatch object name in code) at certain rotation of the player.
if (camRotationToWatch.transform.localEulerAngles.x >= navigationCanvasXMinmumLimit && camRotationToWatch.transform.localEulerAngles.x <= navigationCanvasXMaximumLimit)
{
if (!navCanvasHasDisplay)
{
navigationCanvas.SetActive(true);
//Debug.Log(camRotationToWatch.transform.forward);
Vector3 navCanvas = camRotationToWatch.transform.position + camRotationToWatch.transform.forward * navCanvasDisplayDistanceFromCam;
navCanvas = new Vector3(navCanvas.x, 2f, navCanvas.z);
navigationCanvas.transform.position = new Vector3(navCanvas.x, navCanvas.y, navCanvas.z);
navigationCanvas.transform.rotation = camRotationToWatch.transform.rotation;
navCanvasHasDisplay = true;
}
}
else
{
//navigationCanvas.SetActive(false);
if (locationPanel.activeSelf == false && infoPanel.activeSelf == false) {
navigationCanvas.SetActive(false);
navCanvasHasDisplay = false;
}
}
This code is actually work fine when camRotationToWatch object rotate from down to up and Canvas show at correct position but as I try to to rotate camRotationToWatch from up to down it display(active) Canvas at very top position. How can I restrict canvas to show at same position (No matter player rotate from up to down or down to up) but display on front of the player object?
Kinda hard trying to figure out what exactly you want to do. But this did what I think you where trying to do
public GameObject follow; // The object you want to rotate around
public float distance = 2; // Distance to keep from object
private void Update() {
Vector3 forward = follow.transform.forward;
forward.y = 0; // This will result in Vector3.Zero if looking straight up or down. Carefull
transform.position = follow.transform.position + forward * distance;
transform.rotation = Quaternion.LookRotation(forward, Vector3.up);
}
I believe your "unexpected behavior" is due to the use of euler angles since they are not always entirely predictable. Try using Quaternions or Vector3.Angle() when possible.
If you want to limit the angle (say... if looking down or up more than 45° disable the object) you could do the following:
if (Vector3.Angle(forward, follow.transform.forward) > maxAngle) { ... }
This probably isn't a complete answer but something that might help. This line:
Vector3 navCanvas = camRotationToWatch.transform.position + camRotationToWatch.transform.forward * navCanvasDisplayDistanceFromCam;
You are creating a position at a fixed distance from camRotationToWatch. But if that object is looking up or down, that position is not horizontally at navCanvasDisplayDistanceFromCam. If it's looking straight up, then this position is in fact directly above.
So when you do this to set a fixed vertical height:
navCanvas = new Vector3(navCanvas.x, 2f, navCanvas.z);
you aren't getting the distance from camRotationToWatch that you think you are.
Instead of using camRotationToWatch.transform.forward, create a vector from it and zero out the Y component, and normalize before using it to offset the position. (You will need to watch out for zero length vectors with that though).
Whether that fixes your problem or not, it's too hard to guess but it should help improve your results some.
EDIT: Here is an example of how you can avoid the issue with the canvas being too close:
Vector3 camForward = camRotationToWatch.transform.forward;
camForward.y = 0;
if (camForward.magnitude == 0)
{
//TODO: you'll need to decide how to deal with a straight up or straight down vector
}
camForward.Normalize();
//Note: now you have a vector lying on the horizontal plane, pointing in
//the direction of camRotationToWatch
Vector3 navCanvas = camRotationToWatch.transform.position + camForward *
navCanvasDisplayDistanceFromCam;
//Note: if you want the canvas to be at the player's height (or some offset from),
//use the player's y
navCanvas = new Vector3(navCanvas.x, Player.transform.y, navCanvas.z);
navigationCanvas.transform.position = navCanvas;
Again, this might not fix all your issues but will help to ensure your canvas lies at a set distance horizontally from the Player and will also compensate for the player's up and down motion.
I try to move my character but he moves through the border of the scene.
When I debug it sayscharTransform has 0 0 0 coords in Vector3.
Transform charTransform;
float leftHorizontalBound;
float rightHorizontalBound;
void Start()
{
charTransform = this.transform;
leftHorizontalBound = camera.ViewportToWorldPoint (new Vector3 (0,0, camera.nearClipPlane)).x;
rightHorizontalBound= camera.ViewportToWorldPoint (new Vector3 (1,0, camera.nearClipPlane)).x;
}
void Update()
{
if(charTransform.position.x <= leftHorizontalBound)
{
charTransform.position = new vector2(leftHorizontalBound + 0.1f);
return;
}
if(charTransform.position.x >= rightHorizontalBound)
{
charTransform.position = new vector2(rightHorizontalBound - 0.1f);
return;
}
//MAKE HERE YOUR MOVEMENT BASED ON INPUT.
}
i cant exactly say what is your problem and wish you assume your problem more accurate but i think you are working something like a boad game with a fixed camera and something like a ball always moves and you just want to keep that object in the scene.
in your code you defined a position by variables and made a position check for every frame. thats not what basically is done in unity and there will be problems. you can make an empty object and put in on the borders you want and check the position of that object with your moving object.
your next way is make an object and add a collider component to it. if your game is 3d add a collider and if its 2d game add a 2d collider and a collider to moving object and after that it never moves toward the borders but still there will be some limits so if it didnt work i think you should add a rigidBody to both of them.