Getting objects to move back and forth in unity? - c#

I've recently started learning c# and unity and we're supposed to make a game where a ball rolls around a maze, is in danger of being destroyed by an enemy, and a message pops up when you reach the end. I have most of this done; however, my enemies, who are supposed to move back and forth and destroy the ball when touched, don't work. The walls and floor explodes out when the game is started and I'm not even sure they work at all. In our current assignment, we have to add classes and add another player (which I'm pretty sure I know how to do already). Here's my current code for my enemy class:
using UnityEngine;
using System;
[System.Serializable]
public class Boundary
{
public float xMin, xMax;
}
public class BadGuyMovement : MonoBehaviour
{
public Transform transformx;
private Vector3 xAxis;
private float secondsForOneLength = 1f;
public Boundary boundary;
void Start()
{
xAxis = Boundary;
}
void Update()
{
transform.position = new Vector3(Mathf.PingPong(Time.time, 3), xAxis);
}
void OnTriggerEnter(Collider Player)
{
Destroy(Player.gameObject);
}
}
On lines 21 (xAxis = Boundary;) and 26 (transform.position = new Vector 3) there are errors that I just completely don't understand. If you guys know how to fix it or know of a better way to do something, or at least a better way to move an object back and forth, please let me know!
Thank you so much for taking the time to answer this!

You're getting errors for two reasons, but fairly trivial.
The first error, on line 21 (xAxis = Boundary), you're getting an error because you're assigning a value of type Boundary to a variable of type Vector3.
This is like trying to say an Apple equals an Orange (they don't).
In languages like C#, the types of both the left hand and the right hand of an assignment must be the same.
Simply put
type variable = value; --> Works only if type from the LHS = type from the RHS
Your second error is happening is because you're trying to create a Vector3 with the wrong set of values. The process of creating a type is done through calling the Constructor of the class you're trying to create.
Now, look at the Constructor for a Vector3. One constructor takes 3 parameters of type float and the other takes 2 parameters, again of type float.
You're trying to call the constructor of a Vector3 using a float (from Mathf.PingPong) and a Vector3 (xAxis).
Now that we have that out of the way, try this code.
using UnityEngine;
using System;
[System.Serializable]
public class Boundary
{
public float xMin, xMax;
}
public class BadGuyMovement : MonoBehaviour
{
public Transform transformx;
private Vector3 xAxis;
private float secondsForOneLength = 1f;
public Boundary boundary; //Assuming that you're assigning this value in the inspector
void Start()
{
//xAxis = Boundary; //This won't work. Apples != Oranges.
}
void Update()
{
//transform.position = new Vector3(Mathf.PingPong(Time.time, 3), xAxis); //Won't work, incorrect constructor for a Vector3
//The correct constructor will take either 2 float (x & y), or 3 floats (x, y & z). Let's ping pong the guy along the X-axis, i.e. change the value of X, and keep the values of Y & Z constant.
transform.position = new Vector3( Mathf.PingPong(boundary.xMin, boundary.xMax), transform.position.y, transform.position.z );
}
void OnTriggerEnter(Collider Player)
{
Destroy(Player.gameObject);
}
}

Related

How to make objects float on water in Unity

I've been working on a game for the team seas game jam, and I'm trying to make a boat that will actually float, I've but ran into a issue, so to explain it the way the current script works is it checks for the position of some point on the boat and if the points are below the y level of the plane/water then it will add an upward force to that point. Here's that code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Floater : MonoBehaviour
{
public float depthBeforeSubmerged = 1f;
public float displacementAmount = 3f;
public Transform[] floatPoints;
public Transform Water;
private Rigidbody rb;
private void Start()
{
rb = GetComponent<Rigidbody>();
}
void FixedUpdate()
{
foreach (Transform t in floatPoints)
{
if (t.position.y < Water.position.y) {
// if point is below water add force to said p
float displacementMultiplyer = Mathf.Clamp01(-t.position.y / depthBeforeSubmerged)
* displacementAmount;
rb.AddForceAtPosition(new Vector3(0f, Mathf.Abs(Physics.gravity.y) *
displacementMultiplyer, 0f), t.position,ForceMode.Acceleration);
}
}
}
}
This code works fine but the issue is that when I want to add waves to the plane/water the boat begins to float under the water, because shaders will edit the mesh plane but not the the y pose
of the plane/water it will not detect that and think the water is just sitting still with no elevation changes. So what I'm trying to do is get the vertices at the same x and z position as the points and get there y positions. Here's a diagram:
.
I'd do a racyast from the center of the cube straight up and add a force upward depending on the distance of that raycast, so as it gets lower underwater, it'll get forced up more. I dont know if there is any specific way to do it in the basic physics engine.

Weird Wheel spinning in unity

i was working on a simple car controller script and a humvee model i downloaded. the script works as its supposed to but the car wheels are out of place and are spinning crazy. i tried searching everywhere but didn't found any solution.
here's the code:
using UnityEngine;
public class GroundVehicleController : MonoBehaviour {
public void GetInput()
{
m_horizontalInput = Input.GetAxis("Horizontal");
m_verticalInput = Input.GetAxis("Vertical");
}
private void Steer()
{
m_steeringAngle = maxSteerAngle * m_horizontalInput;
frontDriverW.steerAngle = m_steeringAngle;
frontPassengerW.steerAngle = m_steeringAngle;
}
private void Accelerate()
{
frontDriverW.motorTorque = m_verticalInput * motorForce;
frontPassengerW.motorTorque = m_verticalInput * motorForce;
}
private void UpdateWheelPoses()
{
UpdateWheelPose(frontDriverW, frontDriverT);
UpdateWheelPose(frontPassengerW, frontPassengerT);
UpdateWheelPose(rearDriverW, rearDriverT);
UpdateWheelPose(rearPassengerW, rearPassengerT);
}
private void UpdateWheelPose(WheelCollider _collider, Transform _transform)
{
Vector3 _pos = _transform.position;
Quaternion _quat = _transform.rotation;
_collider.GetWorldPose(out _pos, out _quat);
_transform.position = _pos;
_transform.rotation = _quat;
}
private void FixedUpdate()
{
GetInput();
Steer();
Accelerate();
UpdateWheelPoses();
}
private float m_horizontalInput;
private float m_verticalInput;
private float m_steeringAngle;
public WheelCollider frontDriverW, frontPassengerW;
public WheelCollider rearDriverW, rearPassengerW;
public Transform frontDriverT, frontPassengerT;
public Transform rearDriverT, rearPassengerT;
public float maxSteerAngle = 30;
public float motorForce = 50;
}
The error on Unity console is telling you the problem:
UnassignedReferenceException: The variable frontDriverW of
groundVehicleController has not been assigned. You problably need to
assign the frontDriverW variable of the GroundVehicleController script
in the inspector.
Well, when your script runs, it tries to access the field frontDriverW, but since it was never assigned a value, it throws the mentioned exception.
You need to go in the inspector for the object that contains the GroundVehicleController script and add a value for the frontDriverW field. While you're there, make sure all the other fields have values too, because if they don't, those will also cause the same error.
From the pictures you've show us, it is not possible to know in which object you added the GroundVehicleController script, but just check all of the Humvee objects until you find it in the inspector. My guess is that it will probably be in the object Wheels, or the object Humvee.
a) Check the prefab you've created to see if these offsets are there even on the prefab.
b) You're updating the wheel pose with global positions and rotations. this is probably what is causing the offsets. try setting the pose local, or just make the wheel meshes follow whatever the wheel colliders are doing, make sure they're all under the same co-ordinate space. Why not just child each individual wheel to it's corresponding wheel collider? theyre just meshes after all.
c) You haven't assigned your wheel meshes at all in your script.
c) play around with different mass values on the RigidBody (keep it heavy), and also consider attaching a physic material to your wheel colliders to reduce slip and spinning (If the car controller already doesnt have a slip setting)

Unity 2D: Gravitational Pull

I'm working on a small game: I want all GameObjects to be pulled into the middle of the screen where they should collide with another GameObject.
I tried this attempt:
using UnityEngine;
using System.Collections;
public class Planet : MonoBehaviour
{
public Transform bird;
private float gravitationalForce = 5;
private Vector3 directionOfBirdFromPlanet;
void Start ()
{
directionOfGameObjectFromMiddle = Vector3.zero;
}
void FixedUpdate ()
{
directionOfGameObjectFromMiddle = (transform.position-bird.position).normalized;
bird.rigidbody2D.AddForce (directionOfGameObjectFromMiddle * gravitationalForce);
}
}
sadly I can't get it to work. I've been told that I have to give the object that is being pulled another script but is it possible to do this just with one script that is used on the object that pulls?
So first you have a lot of typos / code that doesn't even compile.
You use e.g. once directionOfBirdFromPlanet but later call it directionOfGameObjectFromMiddle ;) Your Start is quite redundant.
As said bird.rigidbody2D is deprecaded and you should rather use GetComponent<Rigidbody2D>() or even better directly make your field of type
public Rigidbody2D bird;
For having multiple objects you could simply assign them to a List and do
public class Planet : MonoBehaviour
{
// Directly use the correct field type
public List<Rigidbody2D> birds;
// Make this field adjustable via the Inspector for fine tuning
[SerializeField] private float gravitationalForce = 5;
// Your start was redundant
private void FixedUpdate()
{
// iterate through all birds
foreach (var bird in birds)
{
// Since transform.position is a Vector3 but bird.position is a Vector2 you now have to cast
var directionOfBirdFromPlanet = ((Vector2) transform.position - bird.position).normalized;
// Adds the force towards the center
bird.AddForce(directionOfBirdFromPlanet * gravitationalForce);
}
}
}
Then on the planet you reference all the bird objects
On the birds' Rigidbody2D component make sure to set
Gravity Scale -> 0
you also can play with the Linear Drag so in simple words how much should the object slow down itself while moving
E.g. this is how it looks like with Linear Drag = 0 so your objects will continue to move away from the center with the same "energy"
this is what happens with Linear Drag = 0.3 so your objects lose "energy" over time

Making a character walk instead topples/flys away

My character (I tried a bunch of types even cubes, but none seem to work) always topple or fly away, I have no idea what part of this code is wrong.
I tried changing the character, the physics, and restrictions (even restrict y-axis movement (both y-axis) and the character still flys away).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class walk : MonoBehaviour
{
private string MoveInputAxis = "Vertical";
private string TurnInputAxis = "Horizontal";
// rotation that occurs in angles per second holding down input
public float rotationRate = 360;
// units moved per second holding down move input
public float moveRate = 10;
private Rigidbody rb;
private void Start()
{
rb = GetComponent<Rigidbody>();
}
// Update is called once per frame
private void Update()
{
float moveAxis = Input.GetAxis(MoveInputAxis);
float turnAxis = Input.GetAxis(TurnInputAxis);
ApplyInput(moveAxis, turnAxis);
}
private void ApplyInput(float moveInput, float turnInput)
{
Move(moveInput);
Turn(turnInput);
}
private void Move(float input)
{
// Make sure to set drag high so the sliding effect is very minimal
// (5 drag is acceptable for now)
// mention this trash function automatically converts to local space
rb.AddForce(transform.forward * input * moveRate, ForceMode.Force);
}
private void Turn(float input)
{
transform.Rotate(0, input * rotationRate * Time.deltaTime, 0);
}
}
I expected it to turn with A and D and move with W and S, instead, it topples over and/or flys away.
Disable gravity (or freeze Y position), freeze rotation on all axes except Y (or whichever is your up axis), and ensure the collider is not spawning already in a collision with the ground (may be clipping when it spawns, causing it to shoot itself away).
Failing this, you could make the rigidbody kinematic, leaving gravity and collisions enabled, and use transform.Translate() to move your character isntead of rigidbody.AddForce()

Can't figure out how to do this all in one function

I am creating a zoo simulation game in Unity 5.4.0f3 using C#. I am trying to spawn a bear prefab clone, do some math, wait for a period of time, do some more math, then destroy the clone object all in one function. Here is what I have right now. The math that I am trying to do in WaitForBearLife() does not happen. Thanks in advance!
using UnityEngine;
using System.Collections;
public class BuyBearButton : MonoBehaviour
{
[SerializeField] GameManager gameManager;
[SerializeField] GameObject bearPrefab;
[SerializeField] Visitor visitor;
GameObject bearClone;
float xMin = -15;
float xMax = 15;
float yMin = 5;
float yMax = 6;
public void BuyBear()
{
Vector2 pos = new Vector2 (Random.Range (xMin, xMax), Random.Range (yMin, yMax));
if (gameManager.myMoney >= gameManager.bearCost)
{
gameManager.numberOfBears++;
gameManager.myMoney = gameManager.myMoney - gameManager.bearCost;
visitor.spawnTime = visitor.spawnTime / visitor.bearAttraction;
bearClone = (GameObject) Instantiate (bearPrefab, pos, transform.rotation);
StartCoroutine (WaitForBearLife ());
Destroy (bearClone, gameManager.bearLife);
}
}
IEnumerator WaitForBearLife()
{
yield return new WaitForSeconds (gameManager.bearLife);
visitor.spawnTime = visitor.spawnTime * visitor.bearAttraction;
}
}
you need to move Destroy function from BuyBear to WaitForBearLife
The problem is that now StartCouroutine call immediately returns and Destroy() gets called right away
I've just copied your code in an empty project, and made placeholder classes for GameManager and Visitor, just with random values in the variables we need in this script. It works just fine... really.So, I'll make you some questions (as I don't have the reputation yet to comment in your post...)
First, there's a script in the bear prefab of any sorts?
This is because it maybe have something that could interrupt the coroutine. It seems unlikely, but you can't know for sure until you try.
Next, how is the declaration of Visitor and GameManager?
The very beginning, when you define the class name and such. In fact, I would like to know more about the variables you used, like gameManager.bearLife and such.
Now, let's see the values.
I've tried with:
public int myMoney = 50000;
public int bearCost = 50;
public int numberOfBears = 0;
public float bearLife = 2.0f;
In GameManager. And:
public float spawnTime = 5;
public float bearAttraction = 2;
In Visitor. It does some weird math, and the logic of this script itself is clearly in development right now, I suppose. But the point is, it works, and with this:
IEnumerator WaitForBearLife()
{
yield return new WaitForSeconds (gameManager.bearLife);
print (visitor.spawnTime);
visitor.spawnTime = visitor.spawnTime * visitor.bearAttraction;
print (visitor.spawnTime);
}
I get 2.5 and 5 in the correspondant prints if I only click once. Some prints (As #Benjamin-lecomte stated) could help you to know if it's even executing that part.
For now, I can't help you without knowing much more. So I'll wait for your answer, then.

Categories