So, i don't really know how to search for a answer to my question, i am working as a game developer for a freelance and my task was to do a "pendulum platform", That's the concept:
I tried a lot of different aproaches, like, for example setting collision boxes in the sides of the platform and when the player enter in the collision box, the platform will move like a pendulum.
But, i always ran into a lot of glitches, and when i managed to solve all of them, the movement felt unnatural.
Here is one of the ways i was trying :
public IEnumerator RotatesTowardsLeft()
{
while (transform.parent.eulerAngles.z < 25 || transform.parent.eulerAngles.z >= 330)//25
{
transform.parent.eulerAngles += new Vector3(0, 0, speed);
yield return new WaitForSeconds(0.01f);
}
currentDirection = Directions.Left;
}
public IEnumerator RotatesTowardsRight()
{
while (transform.parent.eulerAngles.z > 335 || transform.parent.eulerAngles.z < 30)
{
transform.parent.eulerAngles += new Vector3(0, 0, -speed);
yield return new WaitForSeconds(0.01f);
}
currentDirection = Directions.Right;
}
So, if anyone could help me, it would mean a lot, because i feel like i am running out of options...
Try using physics objects, and attaching a ConfigurableJoint to your object. (If you're working in 2D, use DistanceJoint2D) Then you can choose a location for the joint to attach to above it, and it should give you the effect you desire without a bunch of code. Keep in mind, if you are in 3D, there will be a little extra work to set up the ConfigurableJoint, like limiting some of the axes and spring force.
Hope this helps!
Related
I'm kind of new to Unity. As by the title, I am having trouble getting the collisions right in my game. I am using the custom physics script from unity: https://unity3d.com/learn/tutorials/topics/2d-game-creation/scripting-gravity?playlist=17093. In my game, I am experiencing difficulties in disable collisions.
For example, when I use
Physics2D.IgnoreLayerCollision (8, 9);
It doesn't change anything and the two characters still collide. Also, for some reasons, the triggers behave strange and are still affected by collisions. Going near a character with triggers will make him float up. I've been stuck on this for a long time and I'd really appreciate the help.
It is worth noting that I am using custom physics and using a box collider 2d to detect attack ranges etc. Here is some code of that:
Collider2D attackbox = Physics2D.OverlapBox (attackPos.position, new Vector2 (attackRangeX, attackRangeY), 0, whatIsPlayer);
if (attackbox != null && !isDead && characterController.isDead == false) {
targetVelocity = Vector2.zero;
animator.SetTrigger ("isPunching");
timeBtwAtk = startTimeBtwAtk;
}
and I have individual punch triggers in the animation to detect when the character is actually being hit:
public void SetColliderIndex(int spriteNum)
{
colliders[currentColliderIndex].enabled = false;
currentColliderIndex = spriteNum;
colliders[currentColliderIndex].enabled = true;
}
public void ClearColliderIndex()
{
colliders[currentColliderIndex].enabled = false;
}
void OnTriggerEnter2D(Collider2D col)
{
if (col.tag == "Player")
{
col.GetComponent<CharacterController2D> ().TakeDamage (enemyDamage);
col.GetComponent<CharacterController2D> ().canWait = false;
col.GetComponent<CharacterController2D> ().canControl = false;
}
}
When I use Physics2D.IgnoreLayerCollision (8, 9); I want both specified layers not to interact whatsoever. I don't want any weird shifts, or floating when they pass through each other. Also when I move my player agains the enemy, I don't want him to be able to push him back. I want it to be as if he is running into a wall.
I have answered something similar to this here. Also, if you don't want the player suddenly floating upon collision, you can just set the rigidbody/rigidbody2d type to kinematic, but this mean the object will not be affected by physics. you will have to do that in code.
i think your problem is that at some point the two colliders interact and/or one of the two gets activated back, but from the code that you posted i can't clearly identify the problem if there's any
Allright, I have gameObjects with tag "Enemy" and I collect them like this:
enemies = GameObject.FindGameObjectsWithTag("Enemy");
After that, I am trying to move the first "Enemy":
int newPositionX;
int newPositionY;
bool targetReached = false;
int moveSpeed = 1;
void Update()
{
if (!targetReached)
{
newPositionX = Mathf.FloorToInt(enemies[0].transform.position.x)-1;
newPositionY = Mathf.FloorToInt(enemies[0].transform.position.y);
enemies[0].transform.position = Vector3.MoveTowards(enemies[0].transform.position,
new Vector3(newPositionX, newPositionY), moveSpeed * Time.deltaTime);
targetReached = true;
}
if (Vector3.Distance(enemies[0].transform.position, new Vector3(
newPositionX, newPositionY)) < 0.1f)
{
targetReached = false;
}
}
But an "Enemy" is not making any moves. I can edit that if I remove the:
targetReached = true;
the "Enemy" is moving but there's no way I can stop it. That makes me think that to make sth moving MoveTowards function should be called permanently in the Update?
MoveTowards returns a vector that moves the gameobject one step in the direction of the target.
Also, I am not sure about this, but looking at your code, the if statement that sets the targetReached to false only runs if the targetReached is already false, so you may want to put that out of the if (!targetReached) statement
You probably had the idea that Unity is a complete game engine.
It isn't.
The most basic of things, like tweening and movement aren't provided in the ways just about every other game engine on earth provides them.
So you need to download and setup a plugins and add-ons to get basic functionality.
Search for tweening engines for Unity, and read up about them, as you'll need to understand them and how they incorporate themselves into Unity for the next time you meet missing basics of Unity.
I am trying to achieve a very basic 2D game right now where an enemy is on the screen and it bounces back and forth between set points (50 and 500) kind of like a space invaders sort of thing. My issue is I can only get it to go right, but then not come back towards the left and repeat.
I was messing around with coding it myself before bothering to look into it and actually figure it out but I thought I had something that would work, but well it doesn't, my issue is I don' get why.
My code is supposed to work like a switch, two if statements within the Update loop, one comes on the other goes off, one moves it right the other moves it left, I thought that was fine but it doesn't do that. It moves it right just fine but then the left part just doesn't work.
So, why does the following code not work?
namespace _2D_game_num1
{
class Enemy
{
int health;
Vector2 enemy_location = new Vector2(50, 50);
Vector2 enemy_speed = new Vector2(1, 1);
Player player = new Player("dummy");
public Enemy()
{
health = 100;
}
public void UpdateLocation()
{
//Vector2 player_pos = player.GetLocation();
//if (player_pos.X < 200)
// Using the players location to figure out where the enemy should move
bool right = true;
bool left = false;
if (right)
{
enemy_location.X += enemy_speed.X;
if (enemy_location.X == 500)
{
right = false;
left = true;
}
}
if (left)
{
enemy_location.X -= enemy_speed.X;
if (enemy_location.X == 50)
{
right = true;
left = false;
}
}
}
public Vector2 GetLocation()
{
return enemy_location;
}
}
}
And then in the main Game class I have it so enemy1.UpdateLocation(); is within the Update section correctly (along with my players movement which works fine).
Try this:
public void UpdateLocation()
{
enemy_location.X += enemy_speed.X;
if (enemy_location.X <= 50 || enemy_location.X >= 500)
{
enemy_speed.X = new Vector2(-enemy_speed.X, enemy_speed.Y);
}
}
What we are doing here is moving the enemy based on it's current speed. Then if the location is on the left or right of the screen, change direction.
Sometimes it pays to keep things simple. Get rid of the left and right flags, as they are just confusing things. When you're dealing with Update methods you're typically changing the state of something. The way you had it before, the left and right state was getting reset every time UpdateLocation is called.
Btw, you might want to consider passing in GameTime to your Update methods. Typically, when you're moving things around in real-time you'll want to multiply movement by some kind of deltaTime to keep things smooth on all devices. You're probably getting away with it because by default it'll be a fixed frame rate, but that may not always be the case, so it's a good habit to get into.
Quick disclaimer: I am not a very advanced C# user, being more accustomed to languages like python, so i apologise if the answer is right in front of me.
I've been making a little game for the Google Cardboard, Using the demo scene as a base. I've got some code that checks for a "Trigger Pull" and then should translate the Cardboard cameras up by 10 units.
//Checks For Magnet Trigger
if (Cardboard.SDK.Triggered)
{
//moves player up at a rate of 10u/s
transform.Translate(Vector3.up * 10);
Debug.Log("Triggered_Head");
//Tell Cardboard to maintain new position
}
Currently this works really well for detecting the magnet pull, and it does translate the cardboard. The problem is that almost immediately after translation the cardboard gets teleported back to the base position.
Currently i have this code inserted into the UpdateHead() method (?) from CardboardHead.cs, like so:
// Compute new head pose.
private void UpdateHead() {
if (updated) { // Only one update per frame, please.
return;
}
updated = true;
Cardboard.SDK.UpdateState();
if (trackRotation) {
var rot = Cardboard.SDK.HeadPose.Orientation;
if (target == null) {
transform.localRotation = rot;
} else {
transform.rotation = target.rotation * rot;
}
}
if (trackPosition) {
Vector3 pos = Cardboard.SDK.HeadPose.Position;
if (target == null) {
transform.localPosition = pos;
}
else {
transform.position = target.position + target.rotation * pos;
}
//Checks For Magnet Trigger
if (Cardboard.SDK.Triggered)
{
//moves player up at a rate of 10u/s
transform.Translate(Vector3.up * 10);
Debug.Log("Triggered_Head");
//Tell Cardboard to maintain new position
}
}
if (OnHeadUpdated != null) {
OnHeadUpdated(gameObject);
}
}
Doing this does everything right, but the location is reverted almost instantly (in the next frame i assume). So my question is: How do i make the transform stick, and is there a better way for me to handle this?
Alright, i figured out how to handle movement, and I'm posting the solution here for anyone in the future who can't figure it out. Quick note: I did update to the latest version of the SDK, although that shouldn't make a difference, except for naming.
So, Step 1:
Create an object to use as your controller. I just used one of the prototyping cubes from an asset pack, but whatever will work (empty objects would be best).
Place this object more or less in the center-point of the two cameras.
Parent your GvrMain object to the controller object (by dragging it onto the controller object) as well as any other components you want to move with the player (Guns, GUI's, etc)
Step 2:
Create a script for the controller object.
In the Update() method, add the lines:
if (GvrViewer.Instance.Triggered)
{
transform.Translate(Vector3.up)
}
for older versions replace GvrViewer.Instance with Cardboard.SDK
Customise your movement to your liking, any normal unity functions should work.
Some shortcomings:
You have to repeatedly press the trigger, using while() seems to break unity. This seems pretty easy to fix
The code snippet instantly translates up by 1. Not sure how to do it as a steady acceleration.
Hopefully this helps anyone who had my problem.
I'm just starting with physics, so I'm not always sure about what I'm doing. It's a 2D project but I'm using 3D physical objects like SphereCollider etc..
What I have:
Objects floating in space and affecting each other through gravity:
protected virtual IEnumerator OnTriggerStay(Collider other) {
yield return new WaitForFixedUpdate();
if(other.attachedRigidbody) {
Vector3 offsetVector = this.transform.position - other.transform.position;
float distance = offsetVector.magnitude;
float gravityForce = (other.rigidbody.mass * mass) / Mathf.Pow(distance, 2);
// Clamp gravity.
if(gravityForce > 1.0F) {
gravityForce = 1.0F;
}
other.attachedRigidbody.constantForce.force = offsetVector.normalized * gravityForce;
}
}
There are controllable objects on which the player can click and drag a line away from the object in order to give it a force (shoot) in the opposite direction.
What I want to achieve:
The player should see a rough prediction of the way while aiming. That means that the way-prediction needs to take in account the current velocity, the force which would be applied when the player release the mouse button and the gravity of the surrounding objects.
What I have tried so far:
For testing purposes I just save the computed/predicted positions in an array and draw those positions in OnDrawGizmos().
I wrote a method which returns the gravity influence for a certain position called computeGravityForPosition(Vector3 position).
And thats how I try to calculate the positions:
private void drawWayPrediction() {
Vector3 pos = this.transform.position;
// The offsetVector for the shooting action.
Vector3 forceVector = pos - Camera.main.ScreenToWorldPoint(Input.mousePosition);
forceVector.z = 0.0F;
// The predicted momentum scaled up to increase the strength.
Vector3 force = (forceVector.normalized * forceVector.magnitude);
// 1. I guess that this is wrong, but don't know how to do it properly.
momentum = this.rigidbody.velocity + force;
for(int i = 0; i < predictionPoints.Length; i++) {
float t = i * Time.fixedDeltaTime;
momentum += computeGravityForPosition(pos);
pos += momentum * t * t;
predictionPoints[i] = pos;
}
}
At the beginning, when the objects just slowly approaching each other it looks okay. After the first shot, the prediction is completely wrong. I guess it is because of 1. in the code. Just adding the force to the velocity is probably horrible wrong.
Thank you very much for your time.
EDIT:
I removed seemingly unnessecary parts.
I still think that the main problem lays in 1. in the code. I just don't know how to mix up the current movement of the object (from which I only have the current velocity as far as I know the physics engine of unity) with the new created force:
Vector3 forceVector = pos - Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector3 force = (forceVector.normalized * forceVector.magnitude);
So if you are using a new version of unity probably above 2018, you can use the nice method
Physics.Simulate(dt); // delta time, dt, is the amount of time to simulate.
https://docs.unity3d.com/ScriptReference/Physics.Simulate.html
https://docs.unity3d.com/2018.3/Documentation/ScriptReference/PhysicsScene.Simulate.html
By using this function you can manually advance the simulation.
This method should be applied to a different physics scene.
Therefore I suggest that when you click you will simulate a few physics steps (the more you will simulate the more accurate indication the player will get),
with every step you store the position of the object and when you are done simulating draw a line between all the points.
In my opinion, it should run quite fast if done correctly.
The code should look something like this:
public PhysicsScene physicsScene;
GameObject actualBall;
GameObject simulatedBall;
OnClick() {
simulatedBall.SetPosition(actualBall.transform.position);
if (!physicsScene.IsValid())
return; // do nothing if the physics Scene is not valid.
for (int i=0; i < 10; i++) {
physicsScene.Simulate(Time.fixedDeltaTime);
// store the position.
myPoints.append(simulatedBall.rb.position);
}
// draw a line from the stored points.
}
In addition there is this video that I hope will help, good luck
https://www.youtube.com/watch?v=GLu1T5Y2SSc
I hope I answered your question and if not tell me :)
Disclaimer : Unfortunately I suck at math so can't provide any code for the calculations.
Now that the legal stuff is out of the way :)
In my opinion you are looking at this all wrong. What you need is to calculate the curve (path of the objects trajectory) and then simply plot the curve in OnDrawGizmos with a line renderer.
You don't need to simulate the behaviour of the object. Not only is this a LOT faster but it's also simpler in terms of TimeScale shenanigans. By changing the TimeScale you are also affecting the TimeScale of your trajectory simulation which will most likely look and feel weird.
By doing a basic trajectory calculation you will not have this issue.
PS: This link might help.