(Unity) Is there a way to animate Line Renderer without code? - unity3d

I'm prototyping a 2D space shooter, and i wanted a secondary special attack that creates a laser, completely kinematic, coming out of the ship's front. I've done the laser using Line Renderer and the Bloom Post Processing effect.
So I was wondering if it is possible to animate the line renderer on the animator.
I've tried to do it but it seems that the animator, as far as I can see on my Unity 2019.2.17f1 version, that it only appears to allow animations for the Line Renderer's material-related stuff, not related to the position array (curve), aside from the Width multiplier property, which I also need but isnt sufficient for the animation
Maybe I'm missing a name but it seems that you cant really modify the parameters if it's not via code.
Any ideas?

I'm not sure if or why it is not possible but most probably it is due to the fact that it is an array unlike all the properties you usually animate which are single values.
What you could do though if it is only supposed to animate e.g. the end point have a component like e.g.
public class LaserController : MonoBehaviour
{
public LineRenderer line;
public bool enableLaser;
public Vector3 endPoint;
private void LateUpdate ()
{
line.enabled = enableLaser;
line.SetPosition(1, endpoint);
}
}
And simply animate the fields of that one.

The answer is there isnt, and i switched to particle system for a more simple use.

Related

Weird results with Transform.TransformDirection()

I'm using portal.TransformDirection() to simulate how the object the code is attached to would rotate if it were a child of the portal object without actually being its child.
This is the code and it works kind of but not really. Only if I rotate the portal Object around the Y axis. It still does something when I rotate around the other axes but not what I'm expecting.
I didn't find anyone else who had this problem so I thought I might ask.
I have a short video that demonstrates how it rotates (https://youtu.be/dfvr4IrA2SU) and here is the code on the object that should rotate with the portal object:
using UnityEngine;
[ExecuteInEditMode]
public class PortalArrow : MonoBehaviour
{
[SerializeField] Transform portal;
[SerializeField] Vector3 eulerRotation;
void LateUpdate()
{
transform.position = portal.position;
transform.eulerAngles = portal.TransformDirection(eulerRotation);
}
}
The variable eulerRotation is just a constant Vector3. nothing special about it.
eulerAngles are no direction and it makes no sense to treat them like one.
The fact that it is also stored as a Vector3 is a pure convinience.
would rotate if it were a child of the portal object without actually being its child.
It sounds like you rather simply want
transform.rotation = portal.rotation;

Unity Aiming Line 2D

I am new at coding with Unity and wanted to create a game where the player should shoot a target. I want to draw a line from the players position to the mouse position and when the player hits space the line disappears and the bullet flies in that direction.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Weapon : MonoBehaviour
{
public Transform firePoint;
public GameObject bulletPrefab;
// Update is called once per frame
void Update()
{
if (Input.GetButtonDown("Fire1")) {
Shoot();
}
}
void Shoot()
{
Instantiate(bulletPrefab,firePoint.position,firePoint.rotation);
}
}
I have this code for showing the bullet
I will but give you some hints about how I would do it (as the aswer should not involve providing your coded solution). The real appropiate question would be once you researched and tried out all of this, the concrete step with a reproducible example where you might have got stuck. Find more info about how to ask a good question here
The functions you need to achieve what you want are Input.mousePosition, the unity lineRenderer and maybe Debug.DrawRay to debug your directions in the screen.
For the concrete step of drawing the line you need to set the Input.mousePosition to the lineRenderer positions with SetPositions in an Update() so that when you shoot, you can make the line dissapear disabling the line renderer component, or resetting the positions or with other alternative depending on the behaviour you might need.
Good luck :)

Unity raycast returns center of object, not a point

I want to create a click-to-move game, and have got a nav-mesh agent with code which almost works, except my character always attempts to move to the same spot, regardless of where I click or the position of the camera. This is my function,
private Vector3 GetClickPosition()
{
Vector2 screenPosition = Input.mousePosition;
Vector3 mouseWorldPosition = cam.ScreenToWorldPoint(screenPosition);
RaycastHit hitPosition;
Physics.Raycast(mouseWorldPosition, cam.transform.forward, out
hitPosition, 100, Floor);
return hitPosition.point;
}
Which is used in an on-click command connecting to the player. Everything is referenced and I'm sure the problem is with this piece of code... Thanks in advance.
My source for this code: https://www.youtube.com/watch?v=LoKNYlWWeSM
The source you reference works for me so perhaps something has gone slightly off in your version.
Try assigning the appropriate layer, the one that is referenced as Floor in your Physics.Raycast method, onto the terrain you want to navigate. You may have missed out on this if you renamed the groundLayer mentioned in the source but didn't create and assign the corresponding layer in the editor. Be sure to also set the floor you are using to be static in the Navigation -> Object tab.
I suspect your problem lies here:
Vector3 mouseWorldPosition = cam.ScreenToWorldPoint(screenPosition);
Physics.Raycast(mouseWorldPosition, cam.transform.forward, out hitPosition, 100, Floor);
ScreenPointToWorldPoint() may already be raycasting to find where the world your mouse is (exactly how Unity determines the vector this method returns is not documented), raycasting again from that point in...the direction the camera is facing is probably screwing with you.
Instead, try using cam.ScreenPointToRay() as the parameter into your raycast.

Make rigid body bounce off the screen edge

I'm currently working on an object that involves bubble-like movement. This object has a rigidbody and a sphere collider.
I use the AddForce method every 1-3 seconds to make it move continuously and slowly.
Now I'd like to know how to make the rigidbody move in the opposite direction (a.k.a bounce off) when they reach the screen edge already. I have already computed the screen edges using ViewportToWorldPoint method.
One ineffective solution that I thought of is to put empty game objects with collider at the edges but that won't work in my case since I'm building for mobile devices which have different screen resolutions/sizes.
Anyone know a good solution for this?
I'm not sure i got the idea. But i think i had the same problem when i was writing an old mobile game.
I had the same idea you did, use empty game objects with box collider on the edges, but then i thought, this isn't responsive, so i wrote this code:
public class Walls_c : MonoBehaviour {
public Transform righttop;
public Transform rightbottom;
public Transform lefttop;
public Transform leftbottom;
// Use this for initialization
void Start () {
righttop.transform.position = Camera.main.ViewportToWorldPoint(new Vector3(1,1,0));
rightbottom.transform.position = Camera.main.ViewportToWorldPoint(new Vector3(1,0,0));
lefttop.transform.position = Camera.main.ViewportToWorldPoint(new Vector3(0,1,0));
leftbottom.transform.position = Camera.main.ViewportToWorldPoint(new Vector3(0,0,0));
}
}
With this, i always get the corners of the screen. It's no fancy... but it works.
Let me now if it works.
In order to get a reflection effect, you need Material. Attach a bouncy material to the edges(gameObject) and let the physics calculate what should be the reaction of collision.
Create a Physics 2D material and set the bounceness to some appropriate value say 0.2.
Regarding your issue:
One ineffective solution that I thought of is to put empty game
objects with collider at the edges but that won't work in my case
since I'm building for mobile devices which have different screen
resolutions/sizes.
If you are working with UI component then dealing with boundaries should not be a problem (since it anchors with different resolution) but if it is not the case you can create a script CameraResizer and an enum Anchor (Left, Right, Top, Bottom) and using the same way ViewportToWorldPoint you can align your empty gameObject (boundary) to any screen size by attaching it the gameObject.
Hope it helps!

How to detect that my object is completely inside a box?

I'm developing a game that you drag and drop objects into boxes and I have no idea what's the best and most efficient way to detect whether my objects are in a box.
I'm well aware of colliders and I'm using BoxColliders and triggers to find out whether my object is touching a box but I want to detect the moment when my object (which we can assume to be sphere for sake of simplicity but later will be a mesh) is completely inside my box trigger/collider.
I read about "Contains" method of colliders but IIRC they just check if one single point inside that collider but I'm interested to know if the whole object is inside the collider.
Thanks in advance folks.
Short answer: If you want 100% accuracy, your algorithm will never be better than O(|V|) (worst case) where V = {all vertices in mesh}, meaning you'd run .Collides() over every vertex and break if you find one that is outside your container.
Longer answer: Several methods exist to subdivide mesh surfaces, examples include: KD-Trees, OcTrees. These are beyond the scope of an SO answer to provide a full implementation, I suggest you see the wiki pages for details.
You could use these methods to divide your mesh up in to smaller sets of vertices. To speed up your algorithm you would start at the root of your subdivision tree and test if that node is contained in your container box. Keep working through the tree until you find a node that is not contained by your box. This will allow your "contains" test to fail faster but ultimately you'll wind up testing every vertex if your box contains your mesh.
Caveat: This solution does not work if your mesh is animated. In that case your best bet is to use the bounds around things like arms, feet, legs, etc and use that information to cull your Contains() tests. Again, you'll end up having to test every vertex if the mesh is fully inside your box.
All boxes have a boxCollider. If an object touches the second box, the object must be inside the first box.
This is not a good solution but, maybe it will be usefull.
Use Renderer.bounds property to get bounding box of your object.
Depending on what object you have and how accurate you want to check it to be inside a collider you might than use one of the simple ways to determine that.
for a more refined and cleaner approach. this would be perfect for what you are doing .
you can check the distance between the object you are dragging and the box .
the box has a x,y,z value which represents its position in space.
so when you drag your gameobject it may be just 0.2 on the x,y, or z away from the centere of your box. so just use this method to calculate the distance between your dragged object and the box.
var other :Transform;
function Update()
{
var dist = Vector3.Distance(other.position, transform.position);
// while dragging
if(dist <10)// 10 being on all 3 axiz .
{
//dragged object.position = box position
}
if (dist == 0)
{
print("i am in the centre of the box");
}
}
thus your gameobject will be in the box .
The box within a box solution above is a good option, but if that won't work (due to variably sized/shaped objects) you might be able to accomplish something with Physics.Raycast or Collider.Raycast. I had a similar problem where I needed to test if arbitrary points were contained inside colliders (many of which were unusual blobby concave objects).
The basic idea is a "bed of nails" approach where I cast rays toward the point from multiple directions. If I hit the outside collider on all of the rays, then I can be pretty confident that the point is contained inside the collider (but still not completely certain). Here's a pic:
In this picture, we're trying to see if the blue point is inside the yellow collider. The GREEN arrows represent successful raycasts (the yellow collider is hit), and the PINK one is unsuccessful (the yellow collider is NOT hit).
Here is a code snippet illustrating this:
public static class CollisionUtils {
private static readonly Vector3[] raycastDirections;
// These are the directions that we shoot rays from to check the collider.
static UltrasoundCollisionUtils() {
raycastDirections = new Vector3[5];
raycastDirections[0] = new Vector3(0,1,0);
raycastDirections[1] = new Vector3(0,-1,-0);
raycastDirections[2] = new Vector3(0,0,1);
raycastDirections[3] = new Vector3(-1.41f, 0, -0.5f);
raycastDirections[4] = new Vector3(1.41f, 0, -0.5f);
}
public static bool IsContained (Vector3 targetPoint, Collider collider) {
// A quick check - if the bounds doesn't contain targetPoint, then it definitely can't be contained in the collider
if (!collider.bounds.Contains(targetPoint)) {
return false;
}
// The "100f * direction" is a magic number so that we
// start far enough from the point.
foreach (Vector3 direction in raycastDirections) {
Ray ray = new Ray(targetPoint - 100f * direction, direction);
RaycastHit dummyHit = new RaycastHit();
// dummyHit because collider.Raycast requires a RaycastHit
if (!collider.Raycast(ray, out dummyHit, 100f)) {
return false;
}
}
return true;
}
}
One way you could adapt this algorithm is rather than use Collider.Raycast, do a Physics.Raycast. If the rays hit anything other than your collider, then you know that your target object isn't entirely in the collider.
Add a BoxCollider which surrounds the whole of the object you are testing for and check its bounds min and max are contained within the BoxCollider its entering ... this may not suit for complex mesh objects but you may be able to get away with it and its cheap
Simply,
You can place a box Collider at the bottom of your container.. If your sphere or whatever object touches that then it is completely inside the container..
There is one method though....not that accurate but will work :
Make four empties with collider(Circle / Box) like four wheels of a car and make the object parent to these empty objects with collider.
Then assign every collider a bool whether it is touched or not....
Count the number of colliders touched along with the actual mesh collider...Roughly estimates the orientation of the overlap. If it is 2 that means touched or overlaped from sideways.
Ex: If two collider + the mesh collider is colliding which means it is overlapped sideways...
I solved it using bounds.contains(vector 3 point).
I placed a single point on the object to be detected, and once it was inside the checking limits, I was able to acknowledge its presence.
public class PointInsideBound : MonoBehaviour
{
public Collider BoundCollider;
private Transform pointToCheck;
private void OnTriggerEnter(Collider other)
{
if (pointToCheck == null)
{
//There is a point on top of the collided object. Getting the reference here.
pointToCheck = other.transform.GetChild(0);
}
}
private void OnTriggerStay(Collider other)
{
if (pointToCheck == null)
{
return;
}
if (BoundCollider.bounds.Contains(pointToCheck.position))
{
Debug.Log(" Point Inside the boxcollider");
BoundCollider.enabled = false;
}
}
}
You should use a collider. This is description. http://docs.unity3d.com/Documentation/ScriptReference/Collider.html