I have a unity game and in it, a rotating game object, which increases its speed when it is clicked.
My problem is that the game does not work as I want it to. Right now, if I click any part of the screen, it increases the game object's speed of rotation. On the other hand, if I keep my finger on the screen, the game object starts to slow down and then starts rotating in the opposite direction.
I want the rotation of the object to increase when I click on it, not just if I click on any part of the screen. Furthermore, I don't know why holding down reverses the direction of rotation.
var speed = 1;
var click = 0;
Screen.orientation = ScreenOrientation.LandscapeLeft;
function Update (){
{
transform.Rotate(0,0,speed);
}
if(Input.GetMouseButton(0))
{
if(speed != 0)
{
speed = 0;
} else {
click++;
speed = click;
}
You must use Input.GetMouseButtonUp or Input.GetMouseButtonDown, NOT A Input.GetMouseButton, this method used for clamping.
Try use this code:
var speed = 1;
var click = 0;
Screen.orientation = ScreenOrientation.LandscapeLeft;
function Update (){
{
transform.Rotate(0,0,speed);
}
if(Input.GetMouseButtonDown(0))
{
if(speed != 0)
{
speed = 0;
} else {
click++;
speed = click;
}
A few issues here:
Firstly:
To increase speed upon clicking on the object only, use raycasting from camera, and check if it hits your object. Your object needs need a collider component on it for this to work.
RaycastHit hit;
Ray ray = camera.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
{
Transform objectHit = hit.transform;
objectHit.Rotate(0,0,speed);
}
Refer to https://docs.unity3d.com/Manual/CameraRays.html -> Raycasting section, for more information.
Secondly:
Input.GetMouseButtonDown(..) // returns true at the instance your mouse button transits from up to down
Input.GetMouseButton(..) // returns true as long as your mouse button is held down
Use Input.GetMouseButtonDown(..) in your Update() method if you want to to do something when you click on it.
Related
In my unity based Android game I wish to add the image dynamically based on the number of questions in each level. The image is shown for reference. Each correct answer will be marked in green and the wrong one in red. I am new to unity and trying hard to find steps to achieve this.
Any help with an example for this requirement will be a great help.
I once wrote a script for dynamically creating buttons based on each level. What I did was creating the first button on the scene and adding the other buttons based on the first one. Below is the shell of my code:
// tutorialButton and levelButtons are public variables which can be set from Inspector
RectTransform rect = tutorialButton.GetComponent<RectTransform> ();
for (int i = 1; i < levelSize; i++) {
// Instantiate the button dynamically
GameObject newButton = GameObject.Instantiate (tutorialButton);
// Set the parent of the new button (In my case, the parent of tutorialButton)
newButton.transform.SetParent (levelButtons.transform);
//Set the scale to be the same as the tutorialButton
newButton.transform.localScale = tutorialButton.transform.localScale;
//Set the position to the right of the tutorialButton
Vector3 position = tutorialButton.transform.localPosition;
position.x += rect.rect.width*i;
newButton.transform.localPosition = position;
}
I am not exactly sure if this is the right approach as it may or may not give unexpected results depending on different screen sizes and your canvas, but hopefully it gives you an idea about dynamically creating objects.
I'm not sure if this helps, but if you have all the images in the scene under a canvas, with this you just need to drag the canvas on the script and use
//level-1 is to keep the array notation
FindObjectOfType<NameOfScript>.ChangeColor(level-1,Color.green);
or you can do also
//level-1 is to keep the array notation
FindObjectOfType<NameOfScript>.RevertColor(level - 1);
This is the script:
//Keep it private but you still see it in inspector
//#Encapsulation :)
[SerializeField]
private Canvas _canvas;
private Image[] _images;
//keep the original colors in case you want to change back
private Color[] _origColors;
void Start () {
_images = GetComponentsInChildren<Image>();
_origColors = new Color[_images.Length];
for (int i = 0; i < _images.Length; i++)
{
_origColors[i] = _images[i].color;
}
}
//Reverts the color of the image back to the original
public void RevertToOriginal(int imageIndex)
{
_images[imageIndex].color = _origColors[imageIndex];
}
//Change to color to the coresponding index, starts from 0
public void ChangeColor(int imageIndex, Color color)
{
_images[imageIndex].color = color;
}
P.S If you want it visible only at the end you can make a method where you enable = (true or false) for the canvas. So you keep it false till the end of the level and you make it true when you want to show, while after every answer you call the ChangeColor depending on the result.
To make it easier you can use:
NameOfScript variableName = FindObjectOfType<NameOfScript>();
and after that you just call
variableName.ChangeColor(level - 1, Color.green);
Also it does not matter where you put the script. I would make some kind of manager(empty GameObject) in the scene and put it there.
I'm using Adobe Flash Professional CS6 to create the game. I'll post the code under. Be noticed that there are two symbol I've created using Flash that are not made by code. These symbols are the Crosshair symbol, and the Hitbox symbol. Basically, the objective of the game is to click the Hitbox symbol. My issue is that I am experiencing what seems to be bottlenecking issues. When I click the Hitbox symbol a lot of times with a fast timer the score doesn't register. I am pressuming that this comes from the (maybe) ineffective movement algorithm. But I can't really seem to find room for improvement. Some help would be appreciated.
Be noticed, I had to change the timer from Timer(1) to Timer(30). This made the bottlenecking issue a little bit better, but made the game less fluent.
Aah, and the reason as to why I am using the directionCheckerY and directionCheckerX variables is that I will later in the development add random movement. A random timer will change these to either 0 and 1, creating random movement.
import flash.events.MouseEvent;
import flash.events.TimerEvent;
// Variables
var directionCheckerX:int=0;
var directionCheckerY:int=0;
var pointChecker:int=0;
// Croshair
var crosshair:Crosshair = new Crosshair();
addChild(crosshair);
Mouse.hide();
function moveCrossEvent (evt: MouseEvent) {
crosshair.x = mouseX;
crosshair.y = mouseY;
evt.updateAfterEvent();
}
// Hitbox
var hitbox:Hitbox = new Hitbox();
addChild(hitbox);
hitbox.x=50;
hitbox.y=50;
// Timer
var myTimer:Timer = new Timer(30);
myTimer.addEventListener(TimerEvent.TIMER, timerEvent);
myTimer.start();
function timerEvent(evt:TimerEvent) {
// Border code (Keeps the Hitbox away from out of bounds)
if (hitbox.x <= 0) {
directionCheckerX = 1;
} else if (hitbox.x >= 550) {
directionCheckerX = 0;
}
if (directionCheckerX == 0) {
hitbox.x-=2;
} else {
hitbox.x+=2;
}
if (hitbox.y <= 0) {
directionCheckerY = 1;
} else if (hitbox.y >= 400) {
directionCheckerY = 0;
}
if (directionCheckerY == 0) {
hitbox.y-=2;
} else {
hitbox.y+=2;
}
}
// EventListeners
stage.addEventListener(MouseEvent.MOUSE_MOVE, moveCrossEvent);
hitbox.addEventListener(MouseEvent.CLICK, hitboxEvent);
stage.addEventListener(MouseEvent.CLICK, stageEvent);
function hitboxEvent (evt:MouseEvent) {
pointChecker+=1;
outputTxt.text = String(pointChecker);
evt.stopImmediatePropagation();
//evt.updateAfterEvent();
}
function stageEvent(evt:MouseEvent) {
pointChecker-=1;
outputTxt.text = String(pointChecker);
}
To be clear, I'm not a game developer.
Actually, sometimes there is no big difference between a Timer with 1 millisecond interval and another one with 30 milliseconds interval because it's depending on the SWF file's framerate or the runtime environment ... but here, what about using an Event.ENTER_FRAME event instead of a Timer ? because as Adobe said here about Timers versus ENTER_FRAME events :
Choose either timers or ENTER_FRAME events, depending on whether content is animated.
Timers are preferred over Event.ENTER_FRAME events for non-animated content that executes for a long time.
and in your case the content is animated (even if your game is still basic).
Then you can use a var to set the speed of your hitbox which you can update at any time :
var speed:int = 2;
function timerEvent(evt:TimerEvent): void
{
// ...
if (directionCheckerX == 0) {
hitbox.x -= speed;
} else {
hitbox.x += speed;
}
// ...
}
Hope that can help.
I'm currently working on a game that pays hommage to Marble Blast Gold/Ultra.
At this point I have text that is positioned with the marble. The text is a child of a canvas and I have a canvas group added to the text. I initially set the alpha of the canvas group to 0 so that you can't see the text.
What I'm trying to do is have it so that when you pick up a power up the text reappears by changing the canvas group's alpha back to 1 and then once the power up is used set it back to 0.
I'm not seeming to have any luck with my current code.
// Super Jump pickup
if (col.gameObject.tag == "Spring")
{
superJumpText.GetComponent<CanvasGroup>().alpha = 1;
canSuperJump = true;
canSuperSpeed = false;
col.gameObject.SetActive(false);
hitSuperJump = true;
Invoke("Display", 20);
}
void Update()
{
//super jump
if (canSuperJump)
{
if (Input.GetKeyDown(KeyCode.Mouse0))
{
Vector3 jump = new Vector3(0, superJumpForce, 0);
GetComponent<Rigidbody>().AddForce(jump);
canSuperJump = false;
superJumpText.GetComponent<CanvasGroup>().alpha = 0;
}
}
}
The only reason this would not work for you is that somewhere in your parent hierarchy you have a gameobject with another canvas group. That would ALWAYS override the child canvas group settings UNLESS you select the 'Ignore Parent Groups' checkbox in the child canvas
I am new to XNA and CSharp programming so I want to learn to make a treasure hunting game as a beginning so I made a player(as a class) which can walk up, down, left and right. I made a Gem class also which the player can collide with and the gem disappears and a sound is played. But I want to make some walls that the player can collide with and stop so I made a class called Tile.cs (The wall class) and I made a void in it
public void CollideCheck(bool tWalk, bool bottomWalk, bool leftWalk, bool rightWalk, Rectangle topRect, Rectangle bottomRect, Rectangle rightRect, Rectangle leftRect)
{
colRect = new Rectangle((int)position.X, (int)position.Y, texture.Width, texture.Height);
if (this.colRect.Intersects(topRect))
{
tWalk = false;
}
else
tWalk = true;
if (this.colRect.Intersects(bottomRect))
{
bottomWalk = false;
}
else
bottomWalk = true;
if (this.colRect.Intersects(leftRect))
{
leftWalk = false;
}
else
leftWalk = true;
if (this.colRect.Intersects(rightRect))
{
rightWalk = false;
}
else
rightWalk = true;
}
Then, in the Game1.cs (The main Class) I made an array of "Tiles":
Tile[] tiles = new Tile[5];
And in the update void I made this:
foreach (Tile tile in tiles)
{
tile.CollideCheck(player.topWalk, player.bottomWalk, player.leftWalk, player.rightWalk,
new Rectangle((int)player.Position.X, (int)player.Position.Y - (int)player.Speed.Y, player.currentAnim.FrameWidth, player.currentAnim.FrameHeight),
new Rectangle((int)player.Position.X, (int)player.Position.Y + (int)player.Speed.Y, player.currentAnim.FrameWidth, player.currentAnim.FrameHeight),
new Rectangle((int)player.Position.X + (int)player.Speed.X, (int)player.Position.Y, player.currentAnim.FrameWidth, player.currentAnim.FrameHeight),
new Rectangle((int)player.Position.X - (int)player.Speed.X, (int)player.Position.Y, player.currentAnim.FrameWidth, player.currentAnim.FrameHeight));
}
All those rectangles are the borders of the player but when I run the game the player doesn't collide with it so is there any way to fix this?
I can post the project if I am not very clear.
Your parameters are in only, but you set their values inside the call. You have to declare them as out variables so that their value is sent back to the caller. Using out also makes sure you always set a value to them before exiting the function.
So change your function declaration to public void CollideCheck(out bool tWalk, out bool bottomWalk, out bool leftWalk, out bool rightWalk, Rectangle topRect, Rectangle bottomRect, Rectangle rightRect, Rectangle leftRect) and you get the values back.
I am trying to animate 4 images of an actor but what i am seeing is only one image and no other change.
function init()
{
i=0;
while(i<ActStandX.length) //ActStandX holds the x locations of actor in a image spritesheet
{
for(var currentFrame=0;currentFrame<10;currentFrame++)
{
ctxBg.clearRect(0,0,800,600); //ctxBg is 2d context of canvas
ctxBg.drawImage(img,ActStandX[i],10,actWidth,actHeight,200,300,60,110);
}
i++;
}
requestAnimFrame(init);
}
i have tried this code so far but no success.
Try this:
var i = 0;
function init()
{
ctxBg.clearRect(0,0,800,600);
ctxBg.drawImage(img,ActStandX[i++],10,actWidth,actHeight,200,300,60,110);
if (i == ActStandX.length) i = 0; // loop the animation
requestAnimFrame(init);
}
Note that it will change frames every time it paints, so it may be faster than you actually want. It isn't hard to limit the incrementation of i based on the time passed, I'm sure you can figure it out. :)