I am building a 3d topdown shooter. The player controls the avatar with the keyboard and the reticule with the mouse.
I found a simple way to implement the reticule based on this article:
https://gamedevbeginner.com/how-to-convert-the-mouse-position-to-world-space-in-unity-2d-3d/
I defined an object which represents the reticule and attached this script:
public class Reticule : MonoBehaviour
{
Camera mainCamera;
Plane plane;
float distance;
Ray ray;
// Start is called before the first frame update
void Start()
{
mainCamera = Camera.main;
plane = new Plane(Vector3.up, 0);
// This would be turned off in the game. I set to on here, to allow me to see the cursor
Cursor.visible = true;
}
// Update is called once per frame
void Update()
{
ray = mainCamera.ScreenPointToRay(Input.mousePosition);
if (plane.Raycast(ray, out distance))
{
transform.position = ray.GetPoint(distance);
}
}
}
This works, but the issue is that the reticule is lagging behind the mouse cursor, and catches up when I stop moving the mouse.
Is this because this method is just slow. Is there another simple way to achieve the same result?
the issue is that the reticule is lagging behind the mouse cursor, and catches up when I stop moving the mouse
That's normal, your mouse cursor is drawn by the graphics driver (with the help of WDM) as fast as the mouse data information comes over the wire, while your game only renders at a fixed framerate (or slower). Your hardware mouse will always be ahead of where your game draws it or anything related to it.
Some things that can help with working around this:
Don't show the system cursor, instead show your own. That way the cursor you show will always be in the same place your game thinks it is (since it drew it) and you won't have this issue. Careful with this however, because if your game's frame rate starts dipping it will be VERY noticeable when your cursor movement isn't smooth anymore.
Don't tie objects to your cursor. The issue doesn't show with normal interactions, like clicking buttons. You will notice this in RTS games when drawing boxes around units, but I struggle to think of another example of this.
Like above, but less restrictive, you could lerp the objects tied to your cursor in place, so they're always and intentionally behind it. It makes it look more gamey, which isn't that bad for a, you know, game. Though I wouldn't do this for a twitchy shooter, of course.
Related
Here is an image of what I'm trying to achieve
As you can tell it's a split screen game, the player is on the left, computer on the right.
there are 3 cameras in the game, main and two player cameras
the player camera MUST be independent of the player and CAN NOT be a child object of the player object, because the ball bounces and rotates while moving, the cameras must not.
when the balls change direction the camera must remain behind the player so the visual appears to show the landscape rotating with the player.
I've searched high and low for anything to put me on the right path but nothing seems to work right.
It should be a smooth transition so lerp and slerp are to slow for instant moving. I know LateUpdate will help with this.
If anyone can point me in the right direction I'd appreciate it.
Many thanks,
Paul
Have a script which takes in an object's position, in this case the player's ball, so you can code the camera as if it was a child of the object.
An simple example code for having a following camera would be something like...
FollowObject.cs
public Transform exampleObject;
private int offset = 5; //How far back the camera will be
void LateUpdate()
{
transform.position = new Vector3(exampleObject.transform.position.x,
exampleObject.transform.position.y,
exampleObject.transform.position.z - offset)
}
I would like to use a characters tongue so instead of shooting a bullet, it goes toward the enemy, licks it, and comes back. I got this wording from this question: Unity shooting with Tongue 2d game (hasn't been answered and is 4+ years old). The only difference is my character moves.
I have this code from looking at a shooting tutorial so when you click the tongue prefab generates and is at the correct angle. I need it to grow on click and shrink back.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LineController : MonoBehaviour
{
public GameObject player;
private Vector3 target;
public GameObject crosshairs;
public GameObject tonguePrefab;
// Start is called before the first frame update
void Start()
{
Cursor.visible = false;
}
// Update is called once per frame
void Update()
{
target = transform.GetComponent<Camera>().ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, transform.position.z));
crosshairs.transform.position = new Vector2(target.x, target.y);
Vector3 difference = target - player.transform.position;
float rotationZ = Mathf.Atan2(difference.y, difference.x) * Mathf.Rad2Deg;
if (Input.GetMouseButtonDown(0))
{
shootTongue(rotationZ);
}
}
IEnumerator shootTongue(float rotationZ)
{
GameObject t = Instantiate(tonguePrefab) as GameObject;
t.transform.position = new Vector2(target.x, target.y);
t.transform.rotation = Quaternion.Euler(0.0f, 0.0f, rotationZ);
yield return new WaitForSeconds(2000);
t.SetActive(false);
}
}
I was also trying to make it disappear after whatever time and with that it doesn't work at all?
If the prefab is just a line with a simple texture I suggest using a line renderer:
Create an empty transform that starts on the mouth and then it move untill it reaches the crosshair. The movement is done using Vector2.MoveTowards.
Your tongue will no be a line renderer component. This line renderer will have 2 points, the start which is static, and the end which you have to update on the Update() for example, to correspond to the positions of the empty transform in item 1.
If you really wish to expand a tongue gameobject instead, then you are going to need a bit of math, this answer has what you need but in 3D:
https://answers.unity.com/questions/473076/scaling-in-the-forward-direction.html
1) I suggest creating sprite/sprite sheet animations with Mecanim or relatively new Skeletal Animation with Anima2D. With these systems you can create nice animations, transitions, even animate the sphere collider to trigger collisions and actions, change active state of your objects, etc. and control the animation with very little code. This way you can get best effects in my opinion.
As tongue is not a bullet... :) You only need one. I don't think you want to Instantiate/Create prefabs every time you press the lick button. Instead you should just turn your tongue object on/off (gameObject.SetActive). You can also change your object active state within the animation. So if you don't know how to code it you can do most of it in the Animation window and use very simple code to play the animation when you press the lick button. Whenever a sphere collider touches something you can tell the Animator Controller to play a 'roll back' animation and it will transition nicely to the start position.
There are many tutorials about Mecanim, Animations, 2D Animations, Anima2D, Animator Controller out there.
2) If you need very good control over the tongue you could create a custom mesh and control it via script but this is far more difficult.
3) The reason why your object is not turning off is probably because you wrote WaitForSeconds(2000) so it will turn off after 2000 seconds - more than half an hour. You should also call it with StartCoroutine(shootTongue()) as it is a Coroutine. Again if you want to turn off the object don't create new ones every time. If you want to keep creating new objects you should Destroy the objects instead. Otherwise you will end up with a lot of deactivated tongues in your scene and I don't think you needs that many tongues.
Currently I am working on a game for people with accessibility restrictions. I am having the issue of locking the player model in a sitting position. If the user does not center themselves in the room the player model will be pulled to a certain direction. I would like to lock the player model in a seat and only allow for arm movements and head rotations, no leaning or moving in the game using the HMD.
Since I am using the Final VR IK asset I have tried using their demo for sitting position in VR and cannot get the player to stay seated naturally. I am not sure how to program this or set restrictions to be able to do this.
Edit: To simplify my question. How do you lock the oculus rift HMD to only allow for rotation and not position tracking.
I figured it out how to lock the HMD into to only allow for rotation and not position tracking. To add a sitting position just use an body animation that's sitting. There are 2 things I did. First I added a line of code to the OVRCameraRig script:
trackingSpace.localPosition = -1 * centerEyeAnchor.localPosition;
This was done right before the RaiseUpdatedAnchorsEvent(); call around line 260 in the UpdateAnchors() method. What this does is it locks the head position and only allows for head rotation.
The second thing I did was write a head relocation script based on #derHugo answer to one of my other questions. What this does is when the space bar is pressed it will move the entire OVRCameraRig position. There must be a parent on OVRCameraRig for this to work In the screen shot below you can see the CameraParent object as the parent. I used a sphere as the relocation object that was placed in the middle of the head of my player model. The reason I had to add this was sometimes when you hit play the player would start at a weird position depending on where the headset was at the beginning. In the screen shot you can see use position tracking as not being checked in the inspector, that is an error. Please keep it selected to prevent screen tearing in the headset
Here is the code for the changing position of player when in game:
public class VRPositionChange : MonoBehaviour
{
public Transform resetPos;
private Transform parent;
private void Awake()
{
// create a new object and make it parent of this object
parent = gameObject.GetComponentInParent<Transform>();
}
// Update is called once per frame
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
// reset parent objects position
parent.position = resetPos.position;
}
}
}
I am trying to learn unity, and made my first own game and stucked at the beginning. The first idea was to drop a box (cube) to the mouse position. There are many videos and posts about getting the mouse position, and i tried to use them. My problem is, the mouse position i got is the camera's position, instead of the plane.
As you can see, it is kinda works, but it isn't fall to the plane.
https://prnt.sc/lmrmcl
My code:
void Update()
{
Wall();
}
void Wall()
{
if (Input.GetMouseButtonDown(0))
{
if (Input.GetMouseButtonDown(0))
{
wall = GameObject.CreatePrimitive(PrimitiveType.Cube);
Rigidbody wallsRigidbody = wall.AddComponent<Rigidbody>();
wall.transform.localScale = new Vector3(0.6f, 0.6f, 0.6f);
wallsRigidbody.mass = 1f;
wallsRigidbody.angularDrag = 0.05f;
wallsRigidbody.useGravity = true;
wallsRigidbody.constraints = RigidbodyConstraints.FreezeRotation;
wall.transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition);
}
Debug.Log(Camera.main.ScreenToWorldPoint(Input.mousePosition));
BoxCollider wallsCollider = wall.AddComponent<BoxCollider>();
wallsCollider.size = new Vector3(1f, 1f, 1f);
}
}
How should i change my code to get the right position?
This isn't a direct answer to your question, but I'm hoping it'll still get you where you need to go.
Prefabs are your friends! I'd highly recommend leveraging them here instead of constructing a cube directly in code.
But first, make sure everything else is set up right. Go ahead and construct a cube by hand in the Editor and make sure that when you hit Play, it falls as you expect. It should, provided it has a Rigidbody, collider, and you have gravity enabled (true by default).
If that works, drag that cube from your Hierarchy view into a folder in the Project view. This creates a prefab. You can now delete the cube from the Hierarchy view.
Update your script to have a public GameObject field, e.g.
public GameObject cubeToCreate;
Then, in the Inspector pane for whatever gameobject has that script attached, you should get a new field, "Cube To Create". Drag your prefab cube into that slot.
Lastly...update your code to wall = Instantiate(cubeToCreate). You'll still need to update the position, but you should be able to drop the rest of the initialization logic you have above, e.g. setting mass and drag.
As for the actual problem, the first thing that concerns me is how do you plan on turning a 2d mouse click into a 3d point? For the axis going "into" the screen...how should the game determine the value for that?
Camera.main.ScreenToWorldPoint accepts a Vector3, but you're passing it a Vector2 (Input.mousePosition, which gets converted to a z=0 Vector3), so the point is 0 units from the camera -- so in a plane that intersects with the camera.
I haven't done this, but I think you'll need to do raycasting of some sort. Maybe create an invisible 2d plane with a collider on it, and cast a physics ray from the camera, and wherever it hits that plane, that's the point where you want to create your cube. This post has a couple hints, though it's geared toward 2D. That might all be overkill, too -- if you create a new Vector3 and initialize it with your mouse position, you can set the z coordinate to whatever you want, but then your cube creation will be in terms of distance from the camera, which is not the best idea.
Hope this helps.
So I've designed a custom HP bar and aligned it where I'd like it to be as well as how I'd like it to look.
However, when I press play (Not full screen mode, haven't even tested for that)either the image background slides slightly right or the green filler image slides to the left.
I have no idea why it's doing this or how to fix it. I'm willing to offer whatever information you require such as code or screenshots of the inspector.
This is a screen shot of the bar as it is in the sceneview canvas.
As you can see when the Play isn't pressed the bar functions normally. The above pic is Half-Full. The below image is Empty.
Part 2 of the issue:
I'm also having trouble with the HP bar rotating properly with the player.
However, when I turn left or right or face up:
]9
So you can see the HP bar doesn't properly rotate with the player's movement; although it does follow perfectly, the bar doesn't rotate accordingly. I can provide some movement code and the code I use to track the position of the player. What I have done was created a sphere and attached it to the player. I then attached the script for tracking the player onto that sphere. I then removed the mesh render and box collider of the sphere.
Health Bar Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PHealth : MonoBehaviour {
[Header("HP Bar Images")]
[SerializeField]
private Image HpBarBG;
[SerializeField]
private Image HpBarFillBar;
private float imgFill = 1;
void Update () {
FillBar()
}
private void FillBar(){
HpBarFillBar.fillAmount = imgFill;
}
}
Player Movement Script
public GameObject player;
public Vector3 localscale;
// public Transform start, end;
[SerializeField]
private float speed = 5;
void Start () {
}
// Update is called once per frame
void Update ()
{
/*
******** RAYCAST TO DETECT WALLS BELOW *******
*/
// WallDetection(); //Cast ray to detect walls
/*
********* MOVEMENT CODE BELOW *********
*/
if (Input.GetKey(KeyCode.W)|| Input.GetKey(KeyCode.UpArrow)) // Move
Forward
{
player.transform.Translate(Vector2.up * speed * Time.deltaTime,
Space.World);
transform.eulerAngles = new Vector2(0, 180);
}
}//End of class
I'd recommend adding your code to your question so we have the full picture. Before you do that, I can only give you some recommendations and suggestions. I'll amend this answer, so it becomes a real answer, afterwards.
In the mean time, what type of canvas are you using? Judging from the hierarchy, I'd imagine it's in either of the screen space modes. Have you considered a world-space canvas parented to your player? I believe it'll naturally rotate in the way that you want it to. Can the players zoom in and out, and is the player character's rotation fixed to 90-degree increments?
In addition, are you sure you want the healthbar to rotate? To be upside down? Won't it be a better idea to keep it fixed in a regular position, above the character's sprite, even if that's technically "below" the character at the time?
Finally, if you don't mind me asking: why Unity 5? It's been a couple of major releases after it, and 2018 is almost at its cycle's end. Though to be fair, I don't know if the version will make any difference for this, so I'm just being curious.