everyone!
I ran into the problem. I need to draw a radius of enemy attack. The radius needs to be equal radius of SphereCollider that is hanging on it. I've tried to do it with the help of LineRenderer which draws circle. Yeah, actually it draws circle correctly, but the radius of my circle is less than radius of collider on it, despite the fact that I've given the value of a variable from the GetComponent().
Does anyone know what the problem is?
Part of my code:
float x;
float z;
float change = 2 * (float)Math.PI / segments;
float angle = change;
x = Mathf.Sin(angle) * radius;
_line.SetPosition(0, new Vector3(x, 0, Mathf.Cos(angle) * radius));
for (int i = 1; i < (segments + + 2); i++)
{
x = Mathf.Sin(angle) * radius;
z = Mathf.Cos(angle) * radius;
yield return new WaitForSeconds(drawSpeed);
_line.SetPosition((int)i, new Vector3(x, 0, z));
angle += change;
}
In the comments you mentioned that you get your radius from
float radius = _collider.radius;
where _collider is your SphereCollider.
So note that the SphereCollider.radius
The radius of the sphere measured in the object's local space.
The sphere radius will be scaled by the transform's scale.
It appears to me that either your object or one of its parent is somehow scaled differently than 1,1,1 in which case the actual final radius will be influenced by that scale.
You would need to scale the radius accordingly by the transform.lossyScale like e.g.
// Get the lossyScale
// this is the localScale of all parent objects and this localScale combined
var lossyScale = _collider.transform.lossyScale;
// find the biggest extends of the lossyScale
// if you already know they are always equal anyway simply use e.g. lossyScale.x instead
float maxScale = 0;
for(var i = 0; i < 3; i++)
{
maxScale = Mathf.Max(maxScale, Mathf.Abs(lossyScale[i]);
}
float radius = _collider.radius * maxScale;
It's a little hacky, but I've used a sphere outline sprite for just this sort of thing. Just put it on the game object and make sure it is scaled same as your collider. No need for fancy line drawing.
Don't use collider component for the enemy attack range!
Instead of adding a circle collider component you should a collider via code & physics.
What should you do?
This is an example of using a collider via code & physics:
float theCircleRadios = /* You radios */;
Collider2D[] detectedEnemiesColliders = Physics2D.OverlapCircleAll(theCirclePosition, theCircleRadios, DetectedLayers);
Then make your line lineRenderer radios == theCircleRadios.
Related
I wanted to develop a small game. In this game I wanted to include a procedural map generation. It all worked great.
But now I want to find out the height of the heightmap at the mouse position and that doesn't make any sense and I don't understand it
Here a example:
Heightmap
I wrote this script in the void Update()
if (Input.GetMouseButtonDown(0))
{
Vector3 mousePos = Input.mousePosition;
float x = (mousePos.x / Screen.width) * mapWidth;
float y = (mousePos.y / Screen.height) * mapHeight;
//get height at mouse position
float[,] noiseMap = Noise.GenerateNoiseMap (mapWidth, mapHeight, seed, noiseScale, octaves, persistance, lacunarity, offset);
float height = noiseMap[(int)x, (int)y];
Debug.Log(height);
}
When I try this script above I get very strange values.
Like:
Here at a very black or high place i get: 0.5208731
And here at a white place i get: 0.7484959
But then:
at this white place i get: 0.2161063
Something isn't working here and i don't understand it.
Any tips on how to move an object back and forth sinusoidally (like a pendulum, but in a linear path) along a specified 3D vector? I've got the sinusoidal motion and the vector, but I can't figure out how to combine the two.
The following are the two pieces of code I have; the vector is specified using angles from the origin.
I'm very new to coding, so please forgive me for any mistakes in the code.
This moves the object in the sinusoidal path about the origin - this is the motion I want to achieve along the 3D vector.
float rodPositionZsin = pathLength * Mathf.Sin(Time.time) + position;
transform.position = new Vector3(0, 0, rodPositionZsin);
This will move the object along the vector in the X and Y dimensions, but I'm stumped for what to do in the Z.
float Xangle = 20;
float Yangle = 50;
float Zangle = 30;
//Position Transformations
float rodPositionZsin = pathLength * Mathf.Sin(Time.time) + position;
float rodPositionY = Mathf.Cos(Yangle*Mathf.PI/180)*pathLength;
float rodPositionX = Mathf.Sin(Xangle * Mathf.PI / 180)*pathLength;
float rodPositionZ = Mathf.Tan(Zangle * Mathf.PI / 180) * pathLength;
transform.position = Vector2.MoveTowards(transform.position, new Vector2(rodPositionX, rodPositionY), pathLength * Mathf.Sin(Time.time));
rodPositionX = transform.position.x;
rodPositionY = transform.position.y;
rodPositionZ = rodPositionZsin + transform.position.z;
transform.position = new Vector3(rodPositionX, rodPositionY, rodPositionZsin);
if you have a vector, you just need to scale it by a sine curve, then set the object's position to that scaled vector.
so in (untested) pseudocode:
Vector3 scaledVector = originalVector* Mathf.Sin(Time.time);
youGameObject.transform.position = scaledVector
You can then add phase, frequency, and amplitude terms in your sine function to change the frequency of oscillation, how far along that vector, and the start position of the oscillation if you want to customize it further.
Edit:
Here’s how to add these.
http://jwilson.coe.uga.edu/EMT668/EMT668.Folders.F97/Feller/sine/assmt1.html
a * sin(b*x +c) + offset.
Where a is amplitude (max distance travelled)
B is wavelength (1/frequency of oscillation)
C is phase ( starting pos) and offset is to move the whole oscillation pattern along the vector ( make it happen away from origin center)
I'm trying to write a script in Unity which creates a type of radial menu around an object the player is directly facing, but the number of buttons in the menu is a variable.
I've generated the angles to the main menu the objects are supposed to appear at easily enough...
// int buttonCount = number of buttons
float buttonWidth = 360 / buttonCount;
for (int i = 1; i <= buttonCount; i++)
{
float maxAngle = buttonWidth * i;
float minAngle;
if (i == 0)
{
minAngle = 0f;
}
else if (i == buttonCount)
{
minAngle = 360 - buttonWidth;
}
else
{
minAngle = buttonWidth * (i - 1);
}
float buttonAngle = (minAngle + maxAngle) / 2;
}
...but now I'm trying to position the button objects at the corresponding angles around the central menu object and I don't know how?
This function takes as parameters the object you want the buttons to go around, the player gameobject so that you can orient the new buttons toward the player, the angle you want the button to be at, and the radius (distance the button will be from the buttonCenter). Its output is the button position in world space. You can call it for each button you want to add.
Vector3 positionButton(GameObject buttonCenter, GameObject player, float angle, float radius) {
//get the up and right vectors from the player object so we can orient the buttons
Vector3 up = player.transform.up;
Vector3 right = player.transform.right;
angle = Mathf.Deg2Rad * angle; //convert degrees to radians. radians=degrees * 2pi / 360
//cos(angle) give an x coordinate, on a unit circle centered around 0
//sin(angle) is the y coordinate on the unit circle
//take those values, multiply them by the up and right vectors to orient them to the player,
//multiply by the radius to move them the correct distance from the buttoncenter,
//and add the buttoncenter position so they circle around the correct point
Vector3 buttonPos =buttonCenter.transform.position + (radius * right * Mathf.Cos(angle)) + (radius* up * Mathf.Sin(angle));
return buttonPos;
}
First, define an origin and distance for each button from it. As you have the angles, you can apply trigonometry which should allow you to find the coordinate of a point given an angle, distance and origin point. The point will be defined by cos() and sin() of the angle.
Have a look at the 2nd section here
I have a cube which i am moving in circle shape (with horizontal key input) is below code suggested.
public class Oscillator : MonoBehaviour {
float timeCounter = 0;
float speed,width, height;
public float yPosition = 30;
// Use this for initialization
void Start () {
speed = 2; width = 10; height = 10;
}
// Update is called once per frame
void Update () {
timeCounter += Time.deltaTime * speed * Input.GetAxis("Horizontal");
float x = Mathf.Sin (timeCounter)* height;
float y = yPosition;
float z = Mathf.Cos (timeCounter) * width;
transform.position = new Vector3 (x, y, z);
}
}
Now my object is moving in circular shape which is fine. Now i want to translate my objects movement into time.
Let suppose
if my object x position is 1 then it should give me time 1.0
if it is 1.5 then it should give me 1.5
it increase or decrease according to x postion of my object (or possibly throught z).
I logged my object's x position which is starting from 0 to 9.999 and then become decrease 0, then -1 to -9 then it become decrease 0 and reached to its initial position. This circular movement x values are strange for me, i am unable to form any formula that can convert my x position into time.
Please can any one help me in this purely mathematics and 3d math problem?
You could try the following:
Get the vector between origin of the circle and the 0 of your circle, like 12 on a clock. This one is constant.
Then you have the vector between the origin of the circle and the current point.
Try the following:
Vector3 from = new Vector3(0,0,1); / This is your 12
Vector3 to = GetCurrentVector();
float angle = Quaternion.FromToRotation(Vector3.up, to - from).eulerAngles.z;
Debug.Log(angle / 360f);
Can anyone see where I am going wrong here.
I have a CameraObject class (its not a camera, simply the Model of a box to represent a "camera") that has a Model and a Position. It also has the usual LoadContent(), Draw() and Update() methods.
However, when I draw the array of Models, I only see 1 model on the screen (well, there might be 3 but they might all be in the same location)?
The Draw() method for the CameraModel class looks like this:
public void Draw(Matrix view, Matrix projection)
{
transforms = new Matrix[CameraModel.Bones.Count];
CameraModel.CopyAbsoluteBoneTransformsTo(transforms);
// Draw the model
foreach(ModelMesh myMesh in CameraModel.Meshes)
{
foreach (BasicEffect myEffect in myMesh.Effects)
{
myEffect.World = transforms[myMesh.ParentBone.Index];
myEffect.View = view;
myEffect.Projection = projection;
myEffect.EnableDefaultLighting();
myEffect.SpecularColor = new Vector3(0.25f);
myEffect.SpecularPower = 16;
}
myMesh.Draw();
}
}
Then in my Game1 class I create an array of CameraObject objects:
CameraObject[] cameraObject = new CameraObject[3];
Which I Initialize() - so each new object should be at +10 from the previous object
for (int i = 0; i < cameraObject.Length; i++)
{
cameraObject[i] = new CameraObject();
cameraObject[i].Position = new Vector3(i * 10, i * 10, i * 10);
}
And finally Draw()
Matrix view = camera.viewMatrix;
Matrix projection = camera.projectionMatrix;
for (int i = 0; i < cameraObject.Length; i++)
{
cameraObject[i].Draw(view, projection);
}
Where view and projection are from my Camera() class which looks like so:
viewMatrix = Matrix.Identity;
projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), 16 / 9, .5f, 500f);
But I only see 1 object drawn to the screen? I have stepped through the code and all seems well but I cant figure out why I cant see 3 objects?
Can anyone spot where I am going wrong?
This is the code in my Camera() class to UpdateViewMatrix:
private void UpdateViewMatrix(Matrix chasedObjectsWorld)
{
switch (currentCameraMode)
{
case CameraMode.free:
// To be able to rotate the camera and and not always have it looking at the same point
// Normalize the cameraRotation’s vectors, as those are the vectors that the camera will rotate around
cameraRotation.Forward.Normalize();
cameraRotation.Up.Normalize();
cameraRotation.Right.Normalize();
// Multiply the cameraRotation by the Matrix.CreateFromAxisAngle() function,
// which rotates the matrix around any vector by a certain angle
// Rotate the matrix around its own vectors so that it works properly no matter how it’s rotated already
cameraRotation *= Matrix.CreateFromAxisAngle(cameraRotation.Right, pitch);
cameraRotation *= Matrix.CreateFromAxisAngle(cameraRotation.Up, yaw);
cameraRotation *= Matrix.CreateFromAxisAngle(cameraRotation.Forward, roll);
// After the matrix is rotated, the yaw, pitch, and roll values are set back to zero
yaw = 0.0f;
pitch = 0.0f;
roll = 0.0f;
// The target is changed to accommodate the rotation matrix
// It is set at the camera’s position, and then cameraRotation’s forward vector is added to it
// This ensures that the camera is always looking in the direction of the forward vector, no matter how it’s rotated
target = Position + cameraRotation.Forward;
break;
case CameraMode.chase:
// Normalize the rotation matrix’s forward vector because we’ll be using that vector to roll around
cameraRotation.Forward.Normalize();
chasedObjectsWorld.Right.Normalize();
chasedObjectsWorld.Up.Normalize();
cameraRotation = Matrix.CreateFromAxisAngle(cameraRotation.Forward, roll);
// Each frame, desiredTarget will be set to the position of whatever object we’re chasing
// Then set the actual target equal to the desiredTarget, can then change the target’s X and Y coordinates at will
desiredTarget = chasedObjectsWorld.Translation;
target = desiredTarget;
target += chasedObjectsWorld.Right * yaw;
target += chasedObjectsWorld.Up * pitch;
// Always want the camera positioned behind the object,
// desiredPosition needs to be transformed by the chased object’s world matrix
desiredPosition = Vector3.Transform(offsetDistance, chasedObjectsWorld);
// Smooth the camera’s movement and transition the target vector back to the desired target
Position = Vector3.SmoothStep(Position, desiredPosition, .15f);
yaw = MathHelper.SmoothStep(yaw, 0f, .1f);
pitch = MathHelper.SmoothStep(pitch, 0f, .1f);
roll = MathHelper.SmoothStep(roll, 0f, .1f);
break;
case CameraMode.orbit:
// Normalizing the rotation matrix’s forward vector, and then cameraRotation is calculated
cameraRotation.Forward.Normalize();
// Instead of yawing and pitching over cameraRotation’s vectors, we yaw and pitch over the world axes
// By rotating over world axes instead of local axes, the orbiting effect is achieved
cameraRotation = Matrix.CreateRotationX(pitch) * Matrix.CreateRotationY(yaw) * Matrix.CreateFromAxisAngle(cameraRotation.Forward, roll);
desiredPosition = Vector3.Transform(offsetDistance, cameraRotation);
desiredPosition += chasedObjectsWorld.Translation;
Position = desiredPosition;
target = chasedObjectsWorld.Translation;
roll = MathHelper.SmoothStep(roll, 0f, .2f);
break;
}
// Use this line of code to set up the View Matrix
// Calculate the view matrix
// The up vector is based on how the camera is rotated and not off the standard Vector3.Up
// The view matrix needs an up vector to fully orient itself in 3D space, otherwise,
// the camera would have no way of knowing whether or not it’s upside-down
viewMatrix = Matrix.CreateLookAt(Position, target, cameraRotation.Up);
}
I'm not seeing in your code where your cameraObject[n].Position (which is probably the only thing that uniquely differentiates the position between the three models) is affecting the effect.World property.
effect.World = transforms[myMesh.ParentBone.Index];
does not typically take individual model position into account.
Try something like this:
for (int i = 0; i < cameraObject.Length; i++)
{
cameraObject[i].Draw(view, projection, cameraObject[i].Position);
}
//later in the draw method
public void Draw(Matrix view, Matrix projection, Vector3 pos)
{
// ...
myEffect.World = transforms[myMesh.ParentBone.Index] * Matrix.CreateTranslation(pos);
// ...
}
CameraObject[1] & [2] are located at a greater positive Z value than camera[0] and the view matrix is located at the origin & looking in a negative Z direction (remember, the view matrix is the inverted equivalent of a world matrix).
Instead of setting your viewMatrix to Matrix.Identity, set it to this and you might see all three:
viewMatrix = Matrix.CreateLookAt(new Vector3(0,0,75), Vector3.Zero, Vector3.Up);