So here is the code I've been working on:
using System.Collections.Generic;
using UnityEngine;
public class MovePlayer : MonoBehaviour
{
public float sidewaysForce;
public float jumpingForce;
public Rigidbody2D playerRigidbody;
public Transform playerTransform;
private Vector2 forceToAdd;
private bool onGround;
private LayerMask mask = 8;
private void Start()
{
forceToAdd = new Vector2(0, 0);
}
void FixedUpdate()
{
// Basic left/right movement
forceToAdd.x = 0;
forceToAdd.y = 0;
if (Input.GetKey(KeyCode.A))
{
forceToAdd.x = -sidewaysForce;
}
else if (Input.GetKey(KeyCode.D))
{
forceToAdd.x = sidewaysForce;
}
if (Input.GetKey(KeyCode.Space) && onGround == true)
{
forceToAdd.y = jumpingForce;
onGround = false;
}
var something = Physics2D.Raycast(playerTransform.position, Vector2.down, 200000f, mask.value);
Debug.Log(something.collider);
playerRigidbody.AddForce(forceToAdd, ForceMode2D.Impulse);
}
}
And my issue is this: No matter how far I move the player upwards, whether it be to (0,5) or (0, 2044), it will still print out "Hit ground."
I've tried both Physics and Physics2D, I've tried LayerMasking, everything, and yet it won't work. I'm a beginner to Unity btw.
EDIT: I printed Physics2D.Raycast(playerTransform.position, Vector3.down, 2f).colliderand I ended up with "Player," not "Ground," any way to fix this? I tried increasing the distance to 20 and to 2000, but it yields "Player," still. Any ideas?
EDIT #2: I also tried LayerMasks, didn't work still.
The issue is that you are parsing Physics2D.Raycast the wrong parameters. As you can see in the Unity docs, the function takes a Vector2 and not a Vector3.
https://docs.unity3d.com/ScriptReference/Physics2D.Raycast.html
Also for testing Raycasts in Unity, always set the distance parameter to be Mathf.Infinity until you have designed the solution completely. This will save you a headache in debugging. It is also best practice to add a comment explaining that it is a temporary distance value and that it should be changed later.
When posting your questions in the future on forums, ensure that you properly explain your questions as I really had to look through your code to find what the purpose was.
I am going to refrain from commenting about your code design as this is stack overflow and not reddit but I teach programming at university and would love to help if you are open to leaning :)
Related
I got an issue that I've been trying to figure out for some time now and still haven't managed. I created a script for movement which besides using the WASD keys also uses two more buttons to go up and down. The thing is - because of the way I added those buttons for some reason no other function regarding position of the player doesn't work well. For example if I put a collider with a simple on trigger transform.position function for the player to hit - the player is placed on that position but then instantly returned back like there was nothing.
Here is my code. I had tons of iterations how this movement can be done. I did it through physics and controller in several ways but nothing helped. Can you guys tell me if it's the code or some hidden Unity synergy that I don't know about?
(this version works around addForce. Regardless, whatever way I make the up and down functions I cannot move the player with script after that.)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Mov : MonoBehaviour
{
private CharacterController controller;
private Rigidbody Rb;
private Vector3 playerVelocity;
private float playerSpeed =12;
void Start()
{
controller = gameObject.AddComponent<CharacterController>();
Rb = gameObject.GetComponent<Rigidbody>();
}
// Update is called once per frame
void FixedUpdate()
{
Vector3 move = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
Vector3 add =new Vector3 (0, playerSpeed, 0);
controller.Move(move * Time.deltaTime * playerSpeed);
if (Input.GetKey(KeyCode.Mouse1))
{
Rb.AddForce(0, 1200, 0, ForceMode.Acceleration);
}
if (Input.GetKey(KeyCode.Mouse0))
{
Rb.AddForce(0, -1200, 0, ForceMode.Acceleration);
}
}
}
I'm not sure what you mean by "no other function regarding position of the player doesn't work well" but from have you turning "Collision Detection" in your Rigidbody's settings to "Continuous" and "Interpolate" to "Interpolate"? If you don't do so, Unity's collision's may be a bit funky especially if you are going at high speeds.
I have an asteroid field spawned at runtime and droid prefabs the player can release to gather raw material from the asteroids. Everything works but the droids go to the furthest part of the asteroid field to start collecting. I realize I likely need a list of objects to sort through somehow and output the closest.
I suck at coding but managed to get this working by getting a link to the spawned asteroids adding MovementAIRigidbody target to this script & finding one with target = GameObject.Find("AsteroidNew2(Clone)").GetComponent().
This script is based on a GitHub MIT project which is using Vector3 targetPos; I believe to select the target position. Hope this makes sense to a kind soul out there.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace UnityMovementAI
{
public class OffSetPursuitUnityMy : MonoBehaviour
{
MovementAIRigidbody target;
public Vector3 offset;
public float groupLookDist = 1.5f;
SteeringBasics steeringBasics;
OffsetPursuit offsetPursuit;
Separation separation;
NearSensor sensor;
void Start()
{
steeringBasics = GetComponent<SteeringBasics>();
offsetPursuit = GetComponent<OffsetPursuit>();
separation = GetComponent<Separation>();
target = GameObject.Find("AsteroidNew2(Clone)").GetComponent<MovementAIRigidbody>();
sensor = GameObject.Find("SeparationSensor").GetComponent<NearSensor>();
}
void LateUpdate()
{
Vector3 targetPos;
Vector3 offsetAccel = offsetPursuit.GetSteering(target, offset, out targetPos);
Vector3 sepAccel = separation.GetSteering(sensor.targets);
steeringBasics.Steer(offsetAccel + sepAccel);
/* If we are still arriving then look where we are going, else look the same direction as our formation target */
if (Vector3.Distance(transform.position, targetPos) > groupLookDist)
{
steeringBasics.LookWhereYoureGoing();
}
else
{
steeringBasics.LookAtDirection(target.Rotation);
}
}
}
}
GOAL
So I have a space-invaders type game I have made to practise unity and I want to upload it to Itch.io as I have done in the past.
This is a clip of the game.
I switched platforms to WebGL in Build Settings etc, and everything worked fine in Unity.
PROBLEM
However when I built it and uploaded the zip file to Itch.io, the aliens are now a lot faster than usual. (Be aware there may be other things that have changed, I just haven't been able to get to them since it is extremely hard).
CODE
Alien movement:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class AleenController : MonoBehaviour
{
Rigidbody2D rigidbody;
public float speed = 10f;
ScoreController scoreController;
AudioSource aleenDie;
void Start()
{
scoreController = GameObject.Find("Canvas/Score").GetComponent<ScoreController>();
rigidbody = GetComponent<Rigidbody2D>();
aleenDie = GameObject.Find("Main Camera/AleenDie").GetComponent<AudioSource>();
}
void Update()
{
rigidbody.MovePosition(transform.position + new Vector3 (0, -1, 0) * speed * Time.deltaTime);
}
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == "laser")
{
aleenDie.Play();
scoreController.score += 1;
Destroy(gameObject);
}
}
}
NOTE
I am really struggling to find out what is wrong here, since everything is fine in unity. If you do need more details just leave a comment.
If you use physics you should
not set or get values via Transform at all
do things in FixedUpdate
In general though in your case instead of using
void Update()
{
rigidbody.MovePosition(transform.position + new Vector3 (0, -1, 0) * speed * Time.deltaTime);
}
at all simply set the velocity once like e.g.
void Start ()
{
...
rigidbody.velocity = Vector3.down * speed;
}
The rest seems to depend a bit on your screen size. Looks like you are moving your elements in pixel space -> the smaller the display the less pixel distance between the top and bottom -> the faster elements seem to travel.
this is what i want to achieve
I am currently trying to build a RADAR sensor on unity. I am currently using spherecast. How do i set the view angle of the sphere cast and also how do i read the angle at which an object is present in front of it.
What i have used now is Vector3.angle but this shows 160 degrees if the object is directly infront of the radar instead it should be showing 90 degrees.
Ill paste the code that i have implemented below
Any guidance is appreciated.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class spherecast : MonoBehaviour
{
Rigidbody rb;
public List<GameObject> CurrentHitObjects = new List<GameObject>();
//public GameObject curobject;
public float radius;
public float maxdist;
public LayerMask layermask;
public float velocity;
public Time deltatime;
public Vector3 previous;
private Vector3 origin;
private Vector3 direction;
private float hitdist;
// Use this for initialization
void Start()
{
foreach (GameObject cur in CurrentHitObjects)
{
previous = cur.transform.position;
}
}
// Update is called once per frame
void Update()
{
origin = transform.position;
direction = transform.forward;
hitdist = maxdist;
CurrentHitObjects.Clear();
RaycastHit[] hits = Physics.SphereCastAll(origin, radius, direction, maxdist, layermask, QueryTriggerInteraction.UseGlobal);
foreach (RaycastHit hit in hits)
{
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(Camera.main);
if (GeometryUtility.TestPlanesAABB(planes, hit.collider.bounds))
{
float angle = Vector3.Angle(transform.forward, hit.point.normalized);
float degree = Mathf.Acos(angle) * Mathf.Rad2Deg;
Vector3 pos = hit.point;
Debug.Log(hit.collider.name + "position =" + pos);
CurrentHitObjects.Add(hit.transform.gameObject);
hitdist = hit.distance;
Debug.Log(hit.transform.name + "Distance ="+ hitdist);
Debug.Log(hit.collider.name + "Angle = " + angle);
velocity = ((hit.transform.position - previous).magnitude) / Time.deltaTime;
previous = hit.transform.position;
Debug.Log(hit.transform.name + "Velocity =" + velocity);
}
else
{
return ;
}
}
}
private void OnDrawGizmosSelected()
{
Gizmos.color = Color.red;
Debug.DrawLine(origin, origin + direction * hitdist);
Gizmos.DrawWireSphere(origin + direction * hitdist, radius);
}
}
As far as I can tell your code doesn't do anything. My first tip would be to remove all of your commented out code, but after that here is why your code does nothing at all:
You pass an array of objects to your script. Fine so far.
You take this entire array of objects 'CurrentHitObjects' and pass the transform.position of every single object to a single vector3. This means that all the values are overwritten except for the last one. This would be a big problem if you were trying to find the position of every single object. This would instead require vector3[]. But there is another bigger problem.
'previous', which holds transform.position of the objects is not used anywhere. So you are not actually finding the location of anything.
You use start() (which only runs once by the way) to iterate through your object array, but then you clear, CurrentHitObjects.Clear();, right at the beginning of update() (which runs many times per second by the way). The problem here, is that if you hoped to use CurrentHitObjects for anything in your code, you can't because you have wiped it before you even start doing anything with it.
Your raycast[] is shooting towards nothing. Seems to me like it just shoots forward.
You are finding the angle between the forward direction and the forward direction?
Honestly there are a lot of major problems with this code. I don't mean to be harsh, but it looks like you copy and pasted someone else's code and don't know how to use it. This needs a complete rework. If you know how to code I would throw it out and start over again. See my comment on your answer for a better way to do what you want.
If you don't know how to code, you should not be asking for freebie working code on stackoverflow. Try a unity forum instead. If you are trying to get better, see my above comments.
I am trying to make a 2D platformer but my player is not firing on both side I don't know what is wrong with my script.
using UnityEngine;
using System.Collections;
public class Bullet : MonoBehaviour
{
public float bulletSpeed;
public GameObject bullet;
public Transform bulletX;
GameObject clone;
void Update ()
{
if (Input.GetKeyUp ("space"))
{
clone = Instantiate(bullet,new Vector3(bulletX.position.x,bulletX.position.y+0.1f,0f),Quaternion.identity) as GameObject;
if (GameObject.Find ("Player").GetComponent<Player> ().left == true)
bulletSpeed = -30f;
else
bulletSpeed = 30f;
}
bullet.rigidbody2D.velocity = new Vector2(bulletSpeed * 0.5f, 0f);
Destroy (clone, 1f);
}
}
I tried to increase velocity inside the if condition but bullet was moving faster than I needed.
I think your question was very hard to understand what you want to accomplish, but I can see some errors in your code that will render the "clone" you are creating, useless.
The update loop is continuously executing, and you have placed the destroy outside your "Press space" code block. Unity tries to destroy it every frame. Place it inside the space.
I feel it should look more like this:
if (Input.GetKeyUp ("space"))
{
clone = Instantiate(bullet,new Vector3(bulletX.position.x,bulletX.position.y+0.1f,0f),Quaternion.identity) as GameObject;
if (GameObject.Find ("Player").GetComponent<Player> ().left == true)
bulletSpeed = -30f;
else
bulletSpeed = 30f;
bullet.rigidbody2D.velocity = new Vector2(bulletSpeed * 0.5f, 0f);
Destroy (clone, 1f);
}
This might not answer your question, but could you specify more what behaviour you are after? And what object is this script running on? (It is called Bullet with a field referance to another bullet ?)
Debug.Log your bulletSpeed * 0.5f
If I am correct. Even if your Player is Looking at the other way. It is returning
an ABS number meaning (bulletSpeed = -30f & 0.f is != -44954 something but == 44954).
Alternatively you can use AddForce instead of Velocity. It is easier to control.
QUESTION. Why not use Instantiate Vector2?