I have some code that controls a serious of images to produce and 360 spin when dragging mouseX axis. This all worked fine with the code I have used.
I have since had to design for different platform and enlarge the size of the stage i did this by scale to stage check box in the document settings.
While the mouse down is in action the spin works fine dragging through the images as intended but when you you release and start to drag again it doesn't remember the last frame and jumps to another frame before dragging fine again? Why is it jumping like this when all I have done is change the scale of everything?
please see code use to
//ROTATION OF CONTROL BODY X
spinX_mc.stop();
var spinX_mc:MovieClip;
var offsetFrame:int = spinX_mc.currentFrame;
var offsetX:Number = 0;
var percent:Number = 0;
//Listeners
spinX_mc.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
spinX_mc.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
function startDragging(e:MouseEvent):void
{
// start listening for mouse movement
spinX_mc.addEventListener(MouseEvent.MOUSE_MOVE,drag);
offsetX = stage.mouseX;
}
function stopDragging(e:MouseEvent):void
{
("stopDrag")
// STOP listening for mouse movement
spinX_mc.removeEventListener(MouseEvent.MOUSE_MOVE,drag);
// save the current frame number;
offsetFrame = spinX_mc.currentFrame;
removeEventListener(MouseEvent.MOUSE_DOWN, startDragging);
}
// this function is called continuously while the mouse is being dragged
function drag(e:MouseEvent):void
{
trace ("Drag")
// work out how far the mouse has been dragged, relative to the width of the spinX_mc
// value between -1 and +1
percent = (mouseX - offsetX) / spinX_mc.width;
// trace(percent);
// work out which frame to go to. offsetFrame is the frame we started from
var frame:int = Math.round(percent * spinX_mc.totalFrames) + offsetFrame;
// reset when hitting the END of the spinX_mc timeline
while (frame > spinX_mc.totalFrames)
{
frame -= spinX_mc.totalFrames;
}
// reset when hitting the START of the spinX_mc timeline
while (frame <= 0)
{
frame += spinX_mc.totalFrames;
}
// go to the correct frame
spinX_mc.gotoAndStop(frame);
}
By changing
spinX_mc.addEventListener(MouseEvent.MOUSE_MOVE,drag);
offsetX = stage.mouseX;
to
spinX_mc.addEventListener(MouseEvent.MOUSE_MOVE,drag);
offsetX = mouseX;
I seem to of solved the problem and everything runs smoothly again.
Related
So i'm currently making a game, and i've recently added a level editor, but the placing tool does not work how i wanted it to.
https://youtu.be/MuUvnVTL6eg
If you've watched this video, you've probably realized that the block placing works pretty much how placing rectangles in ms pain with alt does, and i want it to work like placing rectangles in ms pain without alt xd.
I'm using this code to place the block:
if (Input.GetKeyDown(KeyCode.Mouse0)){
startDrawPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
tmpObj = spawnObject(blocks[selected].gameObject, startDrawPos);
drawing = true;
}
if (Input.GetKey(KeyCode.Mouse0)){
Vector2 mPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
Vector2 tmpScale = new Vector2(startDrawPos.x - mPos.x, startDrawPos.y - mPos.y);
tmpObj.transform.localScale = tmpScale;
}
if (Input.GetKeyUp(KeyCode.Mouse0))
{
drawing = false;
var scale = tmpObj.transform.localScale;
//Code below destroys the object if it's too small to avoid accidental placements
if (scale.x <= 0.1 && scale.x > -0.1 || scale.y <= 0.1 && scale.y > -0.1)
{
Destroy(tmpObj);
}
}
(All of this code is in the Update() function)
(spawnObject function just instantiates the object prefab)
There is a bit more code but it has nothing to do with the position of the block, it just detect which block is selected and decides if it can be resized or not.
I solved this problem. But because your complete script is not in question, I rebuilt the code with IEnumerator, Here, by pressing the left mouse button, IEnumerator is activated and all commands are grouped in one method to make the code more efficient.
private void Update()
{
if (Input.GetKeyDown(KeyCode.Mouse0)) StartCoroutine(DrawRect());
}
How does the Desktop Rect formula work?
By running IEnumerator, the code first records the starting point of the mouse. It also makes a simple cube because I do not have access to your objects. Now until the mouse is pressed. Resize Rect to the difference between current and recorded points. The only thing is that to avoid ALT control, you have to place it between the current and initial points. The reason for adding the camera forward is to be seen in the camera.
cubeObject.transform.position = (startDrawPos + currentDrawPos) / 2;
The final structure of the DrawRect is as follows:
public IEnumerator DrawRect()
{
drawing = true;
var scale = Vector2.zero;
var startDrawPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
var cubeObject = GameObject.CreatePrimitive(PrimitiveType.Cube);
while (Input.GetKey(KeyCode.Mouse0))
{
var currentDrawPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
cubeObject.transform.position = (startDrawPos + currentDrawPos) / 2 + Camera.main.transform.forward * 10;
scale = new Vector2(startDrawPos.x - currentDrawPos.x, startDrawPos.y - currentDrawPos.y);
cubeObject.transform.localScale = scale;
yield return new WaitForEndOfFrame();
}
if (scale.x <= 0.1 && scale.x > -0.1 || scale.y <= 0.1 && scale.y > -0.1) Destroy(cubeObject);
drawing = false;
}
I wanted my UI to not resize when user is still resizing the game (holding click in the window border) and only when the user has released the mouse the resize event will trigger.
I have tried to achieve it on Unity but so far I only able to detect windows size change, which my script checked every 0.5 second and if detected change it will resize the UI. But of course resizing everything caused a heavy lag, so resizing every 0.5 second is not a good option but resizing every 1 second is not a good idea either because 1 second is considered too long.
The question might be too broad but I have specified the problem as small as possible, how do I detect if user is still resizing the window? And how do I detect if user has stopped resizing the window (stop holding click at window border)?
You can't tell when someone stops dragging a window, unless you want to code a low level solution for ever desktop environment and every operating system.
Here's what worked for me with any MonoBehavior class, using the OnRectTransformDimensionsChange event:
public class StackOverflow : MonoBehaviour
{
private const float TimeBetweenScreenChangeCalculations = 0.5f;
private float _lastScreenChangeCalculationTime = 0;
private void Awake()
{
_lastScreenChangeCalculationTime = Time.time;
}
private void OnRectTransformDimensionsChange()
{
if (Time.time - _lastScreenChangeCalculationTime < TimeBetweenScreenChangeCalculations)
return;
_lastScreenChangeCalculationTime = Time.time;
Debug.Log($"Window dimensions changed to {Screen.width}x{Screen.height}");
}
}
I have some good news - sort of.
When the user resizes the window on Mac or PC,
Unity will AUTOMATICALLY re-layout everything.
BUT in fact ONLY when the user is "finished" resizing the Mac/PC window.
I believe that is what the OP is asking for - so the good news, what the OP is asking for is quite automatic.
However. A huge problem in Unity is Unity does not smoothly resize elements as the user is dragging the mouse to expand the Mac/PC window.
I have never found a solution to that problem. (A poor solution often mentioned is to check the size of the window every frame; that seems to be about the only approach.)
Again interestingly, what the OP mentions
" ..and if window has stopped resizing .."
is automatically done in Unity; in fact do nothing to achieve that.
I needed something like this for re generating a line chart, but as it has too many elements, it would be heavy to do it on every update, so I came up with this, which for me worked well:
public class ToRunOnResize : MonoBehaviour
{
private float screenWidth;
private bool screenStartedResizing = false;
private int updateCounter = 0;
private int numberOfUpdatesToRunXFunction = 15; // The number of frames you want your function to run after, (usually 60 per second, so 15 would be .25 seconds)
void Start()
{
screenWidth = Screen.width; // Identifies the screen width
}
private void Update()
{
if (Screen.width != screenWidth) // This will be run and repeated while you resize your screen
{
updateCounter = 0; // This will set 0 on every update, so the counter is reset until you release the resizing.
screenStartedResizing = true; // This lets the application know when to start counting the # of updates after you stopped resizing.
screenWidth = Screen.width;
}
if (screenStartedResizing)
{
updateCounter += 1; // This will count the updates until it gets to the numberOfUpdatesToRunXFunction
}
if (updateCounter == numberOfUpdatesToRunXFunction && screenStartedResizing)
{ // Finally we make the counter stop and run the code, in my case I use it for re-rendering a line chart.
screenStartedResizing = false;
// my re-rendering code...
// my re-rendering code...
}
}
}
When starting VR tool on mobile and watching directly ahead, I would like to have the view to show the whole model in the center of the screen. The view should be at a slight angle, so I could see the whole building floor. Currently it is directly ahead, which leaves you with a view where you cannot see the whole model. How could I achieve this?
For example, in this Autodesk example, the model is in the center when you enter VR.
http://viewervr.herokuapp.com/
Current code, with what I am trying to adjust the camera position
document.getElementById("toolbar-vrTool").addEventListener("click", function () {
let _navapi = viewer.navigation;
let _camera = _navapi.getCamera();
let xValue = viewer.getCamera().position.x;
let yValue = viewer.getCamera().position.y;
let zValue = viewer.getCamera().position.z;
zValue = zValue * 0.5;
yValue = (zValue * 0.7071) * -1;
_camera.position.set(xValue, yValue, zValue);
});
Current view
View I would like to have
There is a function named fitToView() which will do exactly what you want. But you need to wait for the geometry to be fully loaded before using it. I also added a call to setHomeViewFrom() in the example below to reset the Home position to the fitToView() position result for later navigation.
oViewer.addEventListener (Autodesk.Viewing.GEOMETRY_LOADED_EVENT, onViewerGeometryLoaded) ;
function onViewerGeometryLoaded () {
oViewer.removeEventListener (Autodesk.Viewing.GEOMETRY_LOADED_EVENT, onViewerGeometryLoaded) ;
oViewer.fitToView (true) ;
setTimeout (function () { oViewer.autocam.setHomeViewFrom (oViewer.navigation.getCamera ()) ; }, 1000) ;
}
I'm making a simple 2d pong game. I finished everything now the only problem I have is that the GUI exit or restart button clicks are being recorded when it should not be recorded. Lets say both players fingers are on the screen and they move them so one players finger is 25 units from the button on the x axis and the others -25. These 2 finger touches somehow record as one finger touch in the middle of the screen where my exit button is and the app closes. I have 2 scripts for player controls one for Player 1 and other for player 2
var speed : float = 10;
function Update () {
if (Input.touchCount > 0)
{
var touchDeltaPos:Vector2 = Input.GetTouch(0).position;
if(Input.touchCount>1)
var touchDeltaPos2:Vector2 = Input.GetTouch(1).position;
if(touchDeltaPos.x<Screen.width/2)
{
if(touchDeltaPos.y > Screen.height/2)
{
rigidbody2D.velocity.y = 1*speed;
}
else rigidbody2D.velocity.y = -1*speed;
}
else if(touchDeltaPos2.x<Screen.width/2&&Input.touchCount>1)
{
if(touchDeltaPos2.y > Screen.height/2)
{
rigidbody2D.velocity.y = 1*speed;
}
else rigidbody2D.velocity.y = -1*speed;
}
}
if (Input.touchCount == 0)
rigidbody2D.velocity.y = 0;
rigidbody2D.velocity.x=0;
}
I don't know where your buttons are, but in any case how about making a buffer so it won't be touched by accident like
width = Screen.width/2 - 100
or minus 100 whichever works, the buffer is supposed to take in account the width and height of the finger as well
EDIT
When I say buffer, it means a temporary storage like a variable. So for the code you could do:
var buffer:int = 100;
(touchDeltaPos.x < Screen.width/2 - buffer)
Now why do this? Well, the buffer gives more room for the player's playing area from the exit button.
How to implement an animation in Unity relative to the last position. Normally when an animation is implemented in Unity each loop starts from the same position. I want to implement an animation relative to the last position of the animated object to avoid using forces or math calculations.
How I figured it out:
Unity Animation relative to last position without looping
This code solves the problem regarding animations based on last relative position. In this example, each time we press Fire1 a box will be animated to move from X = 0 to X = 10 Using the animation will help us to provide richer transitions and smooth movements based on curves without the problem of looping.
The idea is to have the animated object inside an empty parent so the animation of the object will be based into local position.
When the animation is finished we update the object and its parent location to match in the last position.
If you have any doubts please ask.
#pragma strict
/**
* Animation in Unity Relative to last position without looping
* #autor Knskank3
* http://stackoverflow.com/users/1287772/knskan3
* 04/09/2014
**/
/*
This code solves the problem regarding animations based on last relative ImagePosition
In this example, each time we press Fire1 a box will be animated to move from X = 0 to X = 10
Using the animation will help us to provide richer transitions and smooth movements based on curves
without the problem of looping
*/
// This var will determine if the animation is started
public var animation_started : boolean = false;
// This var will determine if the animation is finished
public var animation_finished : boolean = true;
function Update () {
// if user triggers Fire1
if( Input.GetButtonUp('Fire1')){
// initialize the flags
animation_started = true;
animation_finished = false;
// Start the animation
// this animation moves the box from local X = 0 to X = 10 using a curve to deaccelerate
animation.Play("boxanim");
}
}
/* This function is trigger at the end of the animation */
public function animationFinished() : void {
animation_finished = true;
}
/*
At the end of the frame if the animation is finished
we update the position of the parent to the last position of the child
and set the position of the child to zero inside the parent.
*/
function LateUpdate () {
// if the animation is finished and it was started
if(animation_finished && animation_started) {
// set the flag
animation_started = false;
// update the parent position
transform.parent.position = transform.position;
// update the box position to zero inside the parent
transform.localPosition = Vector3.zero;
}
}