I am trying to cast a ray from one object to another but it is not working properly.
Result:
Selected object is "EnemyTank" and ray should point to "PlayerTank" but it is not as you can see.
My code:
void FixedUpdate () {
Vector3 dir = player.transform.position - rayOrigin.transform.position;
RaycastHit hitInfo;
dir = dir.normalized;
Debug.DrawRay(rayOrigin.transform.position, dir*maxCheckDistance,Color.red);
}
player variable points to "PlayerTank"
Playertank location:
So there are a few issues that I can see, but straight to the point:
FixedUpdate Runs on a set interval, it isn't every frame. the Method DrawRay() Has a parameter for duration. by default it is set to 0. This means it will only be visible for a single frame. You have 2 choices you can pass in a duration, or you can put this method in update which does run every frame.
void Update () {
Vector3 dir = player.transform.position - rayOrigin.transform.position;
dir = dir.normalized;
Debug.DrawRay(rayOrigin.transform.position, dir*maxCheckDistance,Color.red);
}
However if you are trying to draw a line from one object to another just use Debug.DrawLine()
Debug.DrawLine(rayOrigin.transform.position, player.transform.position, Color.red);
Lastly, avoid using a color for your line that is the same as one of your objects, I am referring to your red cube, and red line. Use a color that will stand out. Say black in this case.
FixedUpdate example:
void FixedUpdate () {
Vector3 dir = player.transform.position - rayOrigin.transform.position;
dir = dir.normalized;
Debug.DrawRay(rayOrigin.transform.position, dir*maxCheckDistance,Color.red, 1.0f);
}
For fun, to have the line change colors using your maxCheckDistance value:
void Update () {
Color lineColor = color.Black;
if(Vector3.Distance(rayOrigin.transform.position, player.transform.position) < maxCheckDistance) {
lineColor = color.White;
}
Debug.DrawLine(rayOrigin.transform.position, player.transform.position, lineColor);
}
EDIT:
It is important to know where your objects actually are, in your question you have a Player object, that you made the parent of 2 cubes. It appears as though you moved those 2 cubes into where you wanted the player to be in the world instead of moving the Player object itself. So your line is drawing correctly, as it is getting the position to the player object, In the future move the parent object instead of the children object.
From your description and screenshot.
You want to draw ray from "EnemyTank" to "PlayerTank".
and in your code "PlayerTank" is player and "EnemyTank" is rayOrigin.
There has draw a small ray from "EnemyTank" to some other direction. So you definitely miss to define your "PlayerTank" in player object.
The direction parameter in DrawRay is a vector in global space.
Thus your ray always points more or less to the origin.
Sorry, my answer is wrong.
Related
I want to make sure that various objects moving at high speed cannot pass through walls or other objects. My thought process was to check via Raycast if a collision has occurred between two moments of movement.
So the script should remember the previous position and check via Raycast for collisions between previous and current position.
If a collision has occurred, the object should be positioned at the meeting point and moved slightly in the direction of the previous position.
My problem is that works outside the map not inside. If I go from inside to outside, I can go through the walls. From outside to inside not.
Obviously I have misunderstood something regarding the application with raycasts.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ObsticalControll : MonoBehaviour
{
private Vector3 positionBefore;
public LayerMask collisionLayer = 9;
private Vector3 lastHit = new Vector3(0, 0, -20);
// Start is called before the first frame update
void Start()
{
positionBefore = transform.position;
}
private void OnDrawGizmos()
{
Gizmos.DrawCube(lastHit, new Vector3(.2f,.2f,.2f));
}
// Update is called once per frame
void Update()
{
Vector3 curruentMovement = transform.position;
Vector2 dVector = (Vector2)transform.position - (Vector2)positionBefore;
float distance = Vector2.Distance((Vector2)positionBefore, (Vector2)curruentMovement);
RaycastHit2D[] hits = Physics2D.RaycastAll((Vector2)positionBefore, dVector, distance, collisionLayer);
if(hits.Length > 0)
{
Debug.Log(hits.Length);
for (int i = hits.Length -1 ; i >= 0 ; i--)
{
RaycastHit2D hit = hits[i];
if (hit.collider != null)
{
Debug.Log("hit");
lastHit.x = hit.point.x;
lastHit.y = hit.point.y;
Vector3 resetPos = new Vector3(hit.point.x, hit.point.y, transform.position.z) + positionBefore.normalized * 0.1f;
transform.position = new Vector3(resetPos.x, resetPos.y, transform.position.z);
}
}
}
positionBefore = transform.position;
}
}
Theres a better way to deal with this that unity has built in.
Assuming the object thats moving at a high speed has a RigidBody(2d in your case) you can set its Collision Detection to Continuous instead of Discrete.
This will help collisions with high speed collision, assuming that its moving at high speed and the wall is not moving.
If for some reason you cannot apply this to your scenario, Ill try to help with the raycast solution.
However, I am still wondering about the collision behavior of my raycast script. That would be surely interesting, if you want to calculate shots or similar via raycast
Alright, so your initial idea was to check if a collision had occurred, By checking its current position and its previous position. And checking if anything is between them, that means a collision has occurred. And you would teleport it back to where it was suppose to have hit.
A better way todo this would be to check where the GameObject would be in the next frame, by raycasting ahead of it, by the distance that it will travel. If it does hit something that means that within the next frame, it would have collided with it. So you could stop it at the collision hit point, and get what it has hit. (This means you wouldn't have to teleport it back, So there wouldn't be a frame where it goes through then goes back)
Almost the same idea but slightly less complicated.
Problem would be that if another object were to appear between them within the next frame aswell, it could not account for that. Which is where the rigidbody.movePosition shines, And with OnCollisionEnter you can detect when and what it collided with correctly. Aswell as without the need to teleport it back
I wanted to make a vertically scrolling background with 3D assets (2D pictures works fine, but i wanted the cool lighting effect), and i kept failing doing something i though would be so simple.
so here's my current progress:
public Vector3 target;
private Transform Top_Top_Left_Rescroll;
void Start (){
target = GameObject.FindGameObjectWithTag ("Top_Top_Left_Rescroll").GetComponent<Transform>();
}
void Update () {
if (gameObject.transform.position.y <= -12) {
gameObject.transform.position = new Vector3 (target.x, target.y, target.z);
}
}
}
The object resets it's position to 0 after the if statement (the rotation and scale weren't affected), and i ran out of ideas to do what i want.
You are passing a Transform to a Vector3.
try :
target = GameObject.FindGameObjectWithTag("Top_Top_Left_Rescroll").transform.position;
ps: I'm not sure if you really want your target position to never change, but you are passing it's value during Start() so you will always place your gameObject in every frame at the same initial position.
I have made a gameobject together with some children gameobject to represent the information to show up when specific circumstances occurred.
I have already ajusted the position of the information gameobject(together with its' children) in the cameraarea. The thing is that I want to move the gameobject(together with its' children) out of the camera, maybe on top or maybe on left. Following is the scratch to demonstrate the position I want to put it:
So that I could move the information gameobject and its' children (Red box) with some movement effect when needed, I have no problem with moving it back but could find an elegant way to move it out of the camera when the game started.
Mostly because I don't know how to calculate the position out of the camera.
Maybe find the upper border of the camera and the size of the gameobject and its children?
I know I could do this by maybe add a marker gameobject to represent the downer border of the information gameobject, and move it until it's not visible, but is there a more elegant way?
Any ideas?
For this one, I would use the following trick: use any method (animation, coroutine, Update method...) to move your item out of screen the way you desire. Then you can use the OnBecameInvisible event which is called when the item does not need to be rendered on any camera anymore. The event will there be used to detect that the parent object moved out of screen, and that you want to stop the current movement. You then just need to define in this event that you want to stop the current moving behavior, and you will be done.
void OnBecameInvisible() {
// Stop moving coroutine, moving in Update or current animation.
}
There are probably more elegant ways of doing it as you said, but I think this method should be enough for what you want to achieve.
It took me time, but I found this way for you, attach this script to your gameObject:
public Renderer rend;
//drag the camera to the script in the inspector
public Camera camera1;
Vector3 bottomleft;
Vector3 topright;
void Start()
{
rend = GetComponent<Renderer>();
//the top-right point of the camera bounds
topright= camera1.ViewportToWorldPoint(new Vector3(0, 0, transform.position.z));
//the bottom-left point of the camera bounds
bottomleft = camera1.ViewportToWorldPoint(new Vector3(1, 1, transform.position.z));
StartCoroutine(MoveUp());
}
IEnumerator MoveUp()
{
//while the position and the height are lower that the Y of top right
while (transform.position.y + rend.bounds.size.y < topright.y)
{
//move the object to the new position (move it up)
transform.position = new Vector3(transform.position.x, transform.position.y + .01f, transform.position.z);
//and wait for 1/100 of a second
yield return new WaitForSecondsRealtime(.001f);
}
}
you can play with the WaitForSecondsRealtime value to change the velocity of moving.
I have the following simple prefab:
When I add this to my scene, it looks like this:
Very neat!
Then I have the following script on my Character:
public class MageController : MonoBehaviour {
public GameObject Spell;
public float SpellSpeed;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (Input.GetKeyDown(KeyCode.H)) {
GameObject newSpell = Instantiate(Spell);
newSpell.transform.position = transform.position;
newSpell.transform.rotation = Quaternion.LookRotation(transform.forward, transform.up);
Rigidbody rb = newSpell.GetComponent<Rigidbody>();
rb.AddForce(newSpell.transform.forward * SpellSpeed);
}
}
}
The goal is of course to make sure that the fireball is spawned correctly (with the tail behind it)
This works when I stand at 0.0.0; it looks like this:
However, if I turn around it looks like this:
As you can see, the rotation of the fireball is not correct (in the above incorrect image it is flying away from me, however, the tail is in front).
What am I doing wrong? How can I make sure that the tail is always correctly placed?
Update after following the guidance of PlantProgrammer
it still turns incorrectly :(
Look at the image below!
You want to use the forward direction of the player and not it's rotation, when instantiating the fireball. (Remember: transform in your script is the player transform not the fireball transform.) Check https://docs.unity3d.com/ScriptReference/Quaternion.LookRotation.html. LookRotation will return the rotation based on player's forward and up vectors.
GameObject newSpell = Instantiate(Spell);
newSpell.transform.position = transform.position;
newSpell.transform.rotation = Quaternion.LookRotation(transform.forward, transform.up);
Not part of your question, but I would also suggest letting the fireball fly in the forward direction of itself not the player (as this leaves more room for later modifications)
rb.AddForce(newSpell.transform.forward * SpellSpeed);
I have just started unity. I have 4 Images(sprites) aligned in a grid. Now i want to move an image to a target position as soon as I touch the image. How can i do that?
I wrote the following code for move:
void Update () {
float step=speed*Time.deltaTime;
transform.position=Vector3.MoveTowards(transform.position,target.position,step);
}
I just don't know to move that particular sprite on which I touch.
Thanks
From http://answers.unity3d.com/questions/420808/how-to-get-position-of-touch-on-touch-screen.html
fingerPos = Input.GetTouch(0).position;
Vector3 pos = fingerPos;
pos.z = transform.position.z;
// simplified check
if (transform.position == Camera.main.ScreenToWorldPoint(pos))
{
// move towards the target as you want
}
Notice that i kept it brief with that if, but, of course, you should check if the touch position is withing the boundaries of your object.