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.
Related
I have a script that faces my player (cube) to its moving direction. It also has a grappling gun, but when he turns to its moving direction, gun turns too and it can't use grappling gun when i try to grapple and object staying on the opposite site of my player.
This is how i turn my player:
private void Flip()
{
if (isFacingRight && HorizontalInput() < 0f || !isFacingRight && HorizontalInput() > 0f)
{
Vector3 localScale = transform.localScale;
isFacingRight = !isFacingRight;
localScale.x *= -1f;
transform.localScale = localScale;
}
}
If I can fix the localScale of my gun, so that it won't multiplied with -1 when i multiply the whole body.
Any idea? Thanks a lot.
As I understand the question: you want to flip the player but not flip the gun (which is a child of the player).
One way of doing this is to organize the Player object like this:
-Player (prefeb, invisible)
--PlayerGraphicChild (Cube, flip this one only)
--PlayerGunChild (don't flip this one).
Another way is to add a new prefeb called Gun, and set the position of that object to one of the children of Player. Organize the hierarchy like this:
-Player (flip this one)
--PlayerGunDolly (flips with parent)
and create a new prefeb:
-Gun (has a component that sets the transform.position to transform of PlayerGunDolly. Does not flip.)
enter image description here I am instantiating prefabs and listing them on a scroll list. I am trying to teleport the player to instantiated prefab position when I click its reference on scroll list listing?
All suggestions are welcome.
From what I understand about your problem (explained in the comments rather than the question), you should be able to do this:
You can instantaneously move an object camera by setting its transform's position to the instantiated prefab's position when the click has occurred. For a camera, you probably have the camera view in X and Y dimension, so you want to move it to the new X and Y position but leave the Z-position as it is.
One potential solution: Add the following script to the GameObject with your Button component. Then add an event-listener on the Button component that points to the newly added script component and choose the MyTeleportingButton.OnClick as the target method. You also need to drag in the camera as a reference in the new script component.
public class MyTeleportingButton : MonoBehaviour
{
public GameObject camera;
public void OnClick()
{
// casting to Vector2 in order to move in 2D only
var currentPosition = camera.transform.position;
var newPosition = transform.position;
// set same depth as camera
newPosition.z = currentPosition.z;
camera.transform.position = newPosition;
}
}
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 am developing endless game . when player dies then camera zoom and focus on player position. i try and almost done. To zoom the camera i use orthographicSize and focus to the player i use transform.LookAt() that focus the player position when player dies.but the problem is when camera Zoom the scene then entire scene gets rotate. i have created CameraScript and attached to the maincamera .
[SerializeField]
private Camera gameCam;
[SerializeField]
private Transform[] target;
IEnumerator ZoomIn(){
while (gameCam.orthographicSize > 3) {
yield return new WaitForSeconds (0.01f);
transform.LookAt (target [index]);
gameCam.orthographicSize -= 0.1f;
}
}
public void ZoomCam(){
StartCoroutine (ZoomIn ());
}
Help me to that Script if any mistake..Thanks..
I think it's happening because you're not setting the worldUp parameter when you're calling transform.LookAt(...).
I suggest using the camera's own current up vector as that parameter, i.e.
transform.LookAt (target [index], transform.up);
I hope that helps!
EDIT:
Of course, this would only work if your camera is originally oriented as you intend it to be. Else, you'll have to use the vector you choose as the second parameter there.
In my game, my player (a ball) doesn't move in the x-axis. The ball just can jump (y-axis).
The level is always translating in the x-axis and give to the player the sensation the ball is moving.
My question is : Is it possible to add a trail renderer (or something like this) to my ball ? To enforce the sensation of moving of the ball ?
As the image .. :
(source: barouch.fr)
Thank you!
Yes you can, and I've proven that it is possible.
As you can see in the image, I nested 5 spheres recursively, each with Z + 1 of its parent.
You're going to need rigidbody for each of them because we're going to AddForce to them.
And here's the important part, the scripts.
I have 3 scripts, named HeadScript, BodyScript, TailScript (kinda like a snake game, so I name them like that)
HeadScript:
void Update () {
if(Input.GetKeyDown(KeyCode.Space)){
rigidbody.AddForce(new Vector3(0, 6, 0), ForceMode.Impulse);
GameObject child = transform.FindChild("Sphere").gameObject;
BodyScript childScript = child.GetComponent<BodyScript>();
childScript.ChildJump();
}
}
HeadScript is only attached to the head (the rightmost sphere), it needs to detect keydown (for jumping), then we add force to itself (only upwards) so it looks like it's jumping. Afterwards, get the child object, (the ball on its left) and call the function ChildJump which is inside BodyScript.
BodyScript:
public void ChildJump(){
Invoke ("Jump", 0.1f);
}
void Jump(){
rigidbody.AddForce(new Vector3(0, 6, 0), ForceMode.Impulse);
GameObject child = transform.FindChild("Sphere").gameObject;
if(child.GetComponent<BodyScript>() == null){
TailScript childScript = child.GetComponent<TailScript>();
childScript.ChildJump();
}
else {
BodyScript childScript = child.GetComponent<BodyScript>();
childScript.ChildJump();
}
}
BodyScript is attached to every sphere except the first and the last. Parent objects call the function ChildJump which contains only 1 function, Invoke.
Invoke is used to call a function after a certain amount of delay. In this code the delay is 0.1s.
The Jump itself will call its child's (the ball on its left) ChildJump function. Now you see why it is kind of recursive.
We added the if condition so we won't get any errors when we get BodyScript component from the last sphere, which isn't there. The last script has only TailScript.
TailScript:
public void ChildJump(){
Invoke ("Jump", 0.1f);
}
void Jump(){
rigidbody.AddForce(new Vector3(0, 6, 0), ForceMode.Impulse);
}
The final script, TailScript only contains AddForce to itself, because it has no child.
Every sphere (except the head) will jump after 0.1s delay from its parent, becoming what you call it, trail renderer.
Now what's left is just to add alpha material for each of them so they become more transparent, and voila! Job's done!