Why can't I compile this little piece of code ?
I'm overriding x and y in my class so that's why I need super.x.
public class SimpleSprite extends Sprite
{
override public function set x(value: Number): void
{
super.x -= 12;
//super.x = super.x - 12;
}
}
// or
public class SimpleSprite2 extends Sprite
{
public function get xx(): Number
{
return super.x;
}
public function set xx(value: Number): void
{
super.x = value;
}
public function SimpleSprite2()
{
xx -= 12;
super.x -= 12;
// Error: Syntax error: expecting semicolon before minusassign.
}
}
I know I can write super.x = super.x - 12; but im lazy and i dont want 2 look 4 these inconsistencies when i get hit by syntax errors im also very much accustomed to those shortcuts with -=
Looks like my IDE (FlashDevelop 4.2.3) bears the blame for this.
There's nothing syntactically wrong with what your doing. Your code works fine in my Flash Builder 4.7.
However, remember that instance.x -= value; is short for
instance.x = instance.x - value;
//ie.
instance.[set]x = instance.[get]x - value;
I mention this because of your top code:
override public function set x(value: Number): void
{
super.x -= 12;
//super.x = super.x - 12;
}
Makes me think you're trying to do something funny. Why are you decrementing in the set function?
If you need to have a seperate x value for a subclass, but can't change the interface (ie. you still want users to be able to say mySubClassInstance.x = 123.0;) do this:
public class DerivedSprite extends Sprite
{
protected var derivedX:Number;
public override function get x():Number
{
super.x = derivedX;
return derivedX;
}
public override function set x(value:Number):void
{
super.x = value;
derivedX = value;
}
public function DerivedSprite()
{
super();
derivedX = super.x;
}
}
Related
How can I call the codes, inside the Update function using a public method?
What I need to archive is, calling Update using another function.
So that Update triggers using that other method.
One more thing, code should run only when a button long press.
Many Thanks four help
using UnityEngine;
using System.Collections;
public class CarController : MonoBehaviour
{
public float speed = 1500f;
public float rotationSpeed = 15f;
public WheelJoint2D backWheel;
public WheelJoint2D frontWheel;
public Rigidbody2D rb;
private float movement = 0f;
private float rotation = 0f;
void Update()
{
rotation = Input.GetAxisRaw("Horizontal");
movement = -Input.GetAxisRaw("Vertical") * speed;
}
void FixedUpdate()
{
if (movement == 0f)
{
backWheel.useMotor = false;
frontWheel.useMotor = false;
}
else
{
backWheel.useMotor = true;
frontWheel.useMotor = true;
JointMotor2D motor = new JointMotor2D { motorSpeed = movement, maxMotorTorque = 10000 };
backWheel.motor = motor;
frontWheel.motor = motor;
}
rb.AddTorque(-rotation * rotationSpeed * Time.fixedDeltaTime);
}
//public void Rotate()
//{
// rotate = true;
// print("aa");
//}
//public void Move()
//{
// rotation = Input.GetAxisRaw("Horizontal");
// movement = -Input.GetAxisRaw("Vertical") * speed;
//}
}
Those are actually two questions.
1. A long press button
The Unity UI.Button hasn't per se a method for a long press but you can use the IPointerXHandler interfaces for implementing that on your own:
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
// RequireComponent makes sure there is Button on the GameObject
[RequireComponent(typeof(Button))]
public class LongPressButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler
{
private void Awake()
{
ResetButton();
}
// set the long press duration in the editor (in seconds)
public float LongPressDuration = 0.5f;
// Here you reference method just like in onClick
public UnityEvent onLongPress;
private float _timer;
private bool _isPressed;
private bool _pressInvoked;
private void Update()
{
// prevent multiple calls if button stays pressed
if (_pressInvoked) return;
// if button is not pressed do nothing
if (!_isPressed) return;
// reduce the timer by the time passed since last frame
_timer -= Time.deltaTime;
// if timeout not reached do nothing
if (!(_timer <= 0)) return;
// Invoke the onLongPress event -> call all referenced callback methods
onLongPress.Invoke();
_pressInvoked = true;
}
// reset all flags and timer
private void ResetButton()
{
_isPressed = false;
_timer = LongPressDuration;
_pressInvoked = false;
}
/* IPointer Callbacks */
// enable the timer
public void OnPointerDown(PointerEventData eventData)
{
_isPressed = true;
}
// reset if button is released before timeout
public void OnPointerUp(PointerEventData eventData)
{
ResetButton()
}
// reset if cursor leaves button before timeout
public void OnPointerExit(PointerEventData eventData)
{
ResetButton();
}
}
This script has to be placed next to the Button component.
You don't reference the callback method(s) in the Button's
onClick but instead in this LongPressButton's onLongPress
and don't forget to adjust LongPressDuration also in the inspector.
Example
2. Calling CarController's Update
I don't know why you want this (I guess you disabled the component but want to call Update anyway)
Solution A
In order to be able to reference that method in the Inspector there are a few options:
Simply make your Update method public
public void Update()
{
rotation = Input.GetAxisRaw("Horizontal");
movement = -Input.GetAxisRaw("Vertical") * speed;
}
wrap the content of Update in another public method and use that one instead:
private void Update()
{
DoUpdateStuff();
}
public void DoUpdateStuff()
{
rotation = Input.GetAxisRaw("Horizontal");
movement = -Input.GetAxisRaw("Vertical") * speed;
}
the other way round (how you requested it) - call Update from another public method:
private void Update()
{
rotation = Input.GetAxisRaw("Horizontal");
movement = -Input.GetAxisRaw("Vertical") * speed;
}
public void DoUpdateStuff()
{
Update();
}
So all that's left is referencing the CarController's Update or DoUpdateStuff method in the LongPressButton's onLongPress event.
Solution B
Alternatively you could add that callback directly on runtime without referencing anything nor making the callback method public so you could directly use private void Update without a wrapper method.
Drawback: For this method you somehow have to get the reference to that LongPressButton in your CarController script instead
public class CarController : MonoBehaviour
{
// Somehow get the reference for this either by referencing it or finding it on runtime etc
// I will asume this is already set
public LongPressButton longPressButton;
private void Awake()
{
// make sure listener is only added once
longPressButton.onLongPress.RemoveListener(Update);
longPressButton.onLongPress.AddListener(Update);
}
private void Update()
{
rotation = Input.GetAxisRaw("Horizontal");
movement = -Input.GetAxisRaw("Vertical") * speed;
}
private void OnDestroy()
{
// clean up the listener
longPressButton.onLongPress.RemoveListener(Update);
}
//...
}
Thanks for your descriptive reply. What I did was change my script to following and added Event Trigger component. Then call the public functions accordingly.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CarMve : MonoBehaviour
{
bool move = false;
bool moveR = false;
public Rigidbody2D rb;
public float speed = 20f;
public float rotationSpeed = 2f;
private void FixedUpdate()
{
if (move == true)
{
rb.AddForce(transform.right * speed * Time.fixedDeltaTime * 100f, ForceMode2D.Force);
}
if (moveR == true)
{
rb.AddForce(transform.right *- speed * Time.fixedDeltaTime * 100f, ForceMode2D.Force);
}
}
/* Will be used on the UI Button */
public void MoveCar(bool _move)
{
move = _move;
}
public void MoveCarR(bool _moveR)
{
moveR = _moveR;
}
}
A problem I've been running into lately involves trying to change a variable indirectly.
e.g.
var health:int = 100;
var currentVar = health; //I want currentVar to equal "health"
var currentVar -= 50; // I want to subtract 50 from health;
trace(health) // 100
I could set health to equal currentVar afterward, but this is not possible in some situations.
How can I make as3 understand I don't want current var to equal what health equals, but health itself?
You cannot create a reference (or pointer) to a basic type in As3.
They are always passed by value.
But you can do this with objects for example.
In your case, an object oriented approach is probably better anyway.
Who's health is it? Who's mana is is?
It's probably one thing that has both mana and health (and probably many other properties)
So whatever function is trying to modify different properties, should receive the whole object instead.
You can (should) define a class that contains all those properties with according setter and getter functions.
Than accept that class as a parameter.
Within that function you can decide what property to modify.
Here's one example how that could look like:
package
{
import flash.display.AVM1Movie;
import flash.display.Sprite;
public class FlashTest extends Sprite
{
public function FlashTest()
{
var hero:Hero = new Hero();
trace(hero.health, hero.mana);
dealDamage(hero);
trace(hero.health, hero.mana);
absorbEnergy(hero);
trace(hero.health, hero.mana);
doRandomThing(hero);
}
private function dealDamage(hero:Hero):void
{
hero.health -= 5;
}
private function absorbEnergy(hero:Hero):void
{
hero.mana -= 5;
}
private function doRandomThing(hero:Hero):void
{
if (Math.random() >= 0.5)
{
hero.health -= 15;
}
else
{
hero.mana -= 15;
}
}
}
}
internal class Hero
{
private var _health:uint = 100;
private var _mana:uint = 100;
public function set health(value:uint):void
{
_health = Math.max(0, value);
if(_health == 0)
{
trace("I'm dead");
}
}
public function get health():uint
{
return _health;
}
public function set mana(value:uint):void
{
_mana = Math.max(0, value);
if(_mana == 0)
{
trace("No more magic");
}
}
public function get mana():uint
{
return _mana;
}
}
In PHP it's trivial to override properties of a class in a subclass. For instance:
class Generic_Enemy {
protected $hp = 100;
protected $str = 5;
//...
}
class Boss_Enemy extends Generic Enemy {
protected $hp = 1000;
protected $str = 25;
}
Which is extremely convenient because at-a-glance you can see in what ways the subclass differs from the parent class.
In AS3 the only way I've found is through getters, which really isn't elegant at all:
public class GenericEnemy {
private var _hp:uint = 100;
private var _str:uint = 25;
public function get hp():uint {
return _hp;
}
public function get str():uint {
return _str;
}
}
public class BossEnemy extends GenericEnemy {
override public function get hp():uint {
return 1000;
}
override public function get str():uint {
return 25;
}
}
Is there a nicer way of doing this that aligns with the PHP approach?
Specifically: let's say I'm writing an API that will let a developer easily spin off his own Enemies. I would rather document that you just have to override hp and str properties rather than explain that they have to create a new getter for each property they wish to override. It's a matter of trying to create the cleanest API and the easiest to document and maintain.
Sometimes ya just have to write the SO question in order to see the (obvious) answer:
public class GenericEnemy {
protected var _hp:uint = 100;
protected var _str:uint = 25;
public function GenericEnemy(){
//...
}
}
public class BossEnemy extends GenericEnemy {
public function BossEnemy(){
_hp = 1000;
_str = 50;
super();
}
}
I have a question about the magic methods getter and setter.
My question is: What is better (faster, safer)?
P.S. This is ActionScript 3, but the question can be answered for other languages like PHP, JavaScript, C# also.
case 1
public class Test extends Sprite
{
private var _test : uint = 0;
public function Test()
{
start();
}
private function start() : void
{
trace(_test); ** Take the private var _test **
}
public function set test(value : uint) : void
{
_test = value;
start();
}
public function get test() : uint
{
return _test;
}
}
or case 2
public class Test extends Sprite
{
private var _test : uint = 0;
public function Test()
{
start();
}
private function start() : void
{
trace(test); ** difference here, take the public function test **
}
public function set test(value : uint) : void
{
_test = value;
start();
}
public function get test() : uint
{
return _test;
}
}
What is the best (fastest) way?
Thanks!
You're about 90% of the way to writing your own test case to find out yourself..
Getters and setters are intended to add control over what happens when a property is set or retrieved or to create read-only or write-only properties.
These benefits greatly outweigh any possible performance differences.
As for those performance differences, here is a test environment:
// Test property.
var _test:uint = 0;
function get test():uint{ return _test; }
function set test(value:uint):void{ _test = value; }
// Direct access test.
function directTest(amt:int):Number
{
// Directly accessing the property.
var t:Number = getTimer();
for(var i:int = 0; i < amt; i++)
{
var temp:uint = _test;
_test = i;
}
return getTimer() - t;
}
// Getter/setter test.
function viaTest(amt:int):Number
{
// Via getter/setter.
var t:Number = getTimer();
for(var i:int = 0; i < amt; i++)
{
var temp:uint = test;
test = i;
}
return getTimer() - t;
}
A quick demonstration of how to use this:
trace("Direct: " + directTest(1000000));
trace("Getter/Setter: " + viaTest(1000000));
And some results that I got:
Amount Direct Get/Set
1000 0 0
5000 0 0
20,000 0 2
150,000 1 14
500,000 2 46
2,000,000 10 184
10,000,000 47 921
I always prefer to use getter and setter also into methods of the same class where they are declared (although I could use privare variables).
Getters and setters hide logic that is required when you have to set or get a class property, so you can modify "what-you-actually-do" inside your setter/getter without worry about impact in client methods.
They also avoid repetition of code.
But this is just my point of view... :)
I am trying to create a basic functionality in AS3.
I have a class like this:
package tax
{
public class Calculator
{
public function Calculator()
{
}
private var grwage:Number;
private var taxes:Number;
private var superannuation:Number;
private var insurance:Number;
private var net:Number;
public function getGrwage():Number {
return grwage;
}
public function setGrwage(grwage:Number):void {
this.grwage = grwage;
}
public function getTaxes():Number {
return grwage;
}
public function setTaxes(taxes:Number):void {
this.taxes = grwage * 0.2;
}
public function getSup():Number {
return superannuation;
}
public function setSup(superannuation:Number):void {
this.superannuation = superannuation * 0.05;
}
public function getIns():Number {
return insurance;
}
public function setIns(insurance:Number):void {
this.insurance = insurance * 0.1;
}
public function getNet():Number {
return net;
}
public function setNet(net:Number):void {
this.net = grwage - taxes - superannuation - insurance;
}
}
}
Just some getters and setters.
And in my mxml file:
import tax.Calculator;
public var calculate:Calculator = new Calculator();
calculate.setGrwage(1000);
trace(calculate.getTaxes());
trace(calculate.getSup());
trace(calculate.getIns());
trace(calculate.getNet());
I get an error 1120 Access to undefinded property when I try to access calculate. Do you have any ideas?
Thanks.
I guess you're mixing up things a bit between getters and setters. If a variable depends on another, you have to write the calculation in its getter. This variable shouldn't exist as a private member and the accesses to it must always be done through the appropriate getter.
for example:
public function getNet():Number {
return getGrwage() - getTaxes() - getSup() - getIns();
}
So here, you only need one setter (setGrwage), you can remove the others ones and put the calculation in the getters.
Note that there is a more appropriate syntax for setters and getters in AS3.
class GetSet
{
private var privateProperty:String;
public function get publicAccess():String
{
return privateProperty;
}
public function set publicAccess(setValue:String):void
{
privateProperty = setValue;
}
}
There are multiple issues with your class. So lets redesign it
The main issue you had was you were not initiating the vars before you accessed them as they had a NULL value the flash player was throwing you that error.
As you can see in the constructor I set a default value of 0 so that they will never be NULL.
package tax {
public class Calculator{
private var _grwage:Number;
private var _taxes:Number;
private var _superannuation:Number;
private var _insurance:Number;
public function Calculator() {
this._grwage = 0;
this._taxes = 0;
this._superannuation = 0;
this._insurance = 0;
}
public function get grwage():Number {
return this._grwage;
}
public function set grwage(val:Number):void {
this._grwage = val;
}
public function get taxes():Number {
return this._taxes;
}
public function set taxes(val:Number):void {
this._taxes = val * 0.2;
}
public function get superannuation():Number {
return this._superannuation;
}
public function set superannuation(val:Number):void {
this._superannuation = val * 0.05;
}
public function get insurance():Number {
return this._insurance;
}
public function set insurance(val:Number):void {
this._insurance = val* 0.1;
}
public function get net():Number {
return this._grwage - this._taxes - this._superannuation - this._insurance;
}
}
}
import tax.Calculator;
public var calculate:Calculator = new Calculator();
//Now due to the fact we are using true setter/getter methods.
calculate.grwage = 1000;
trace( calculate.taxes); // should be 0 as we are defaulting to the initial value
trace( calculate.superannuation );// should be 0 as we are defaulting to the initial value
trace( calculate.insurance );// should be 0 as we are defaulting to the initial value
trace( calculate.net );// should be 1000 as we are defaulting to the initial values of everything but grwage
The answers here are all good, but they all miss the primary point:
You're trying to get your variables before you set them.
import tax.Calculator;
public var calculate:Calculator = new Calculator();
calculate.setGrwage(1000);
trace(calculate.getTaxes());
trace(calculate.getSup());
trace(calculate.getIns());
trace(calculate.getNet());
This will throw an error (due to the way you've set up your class), because you never called setSup(), setIns(), and setNet() before trying to use them.
While your class may not be written in the best way, it is syntactically sound.
Try calling each setter before your getter. I think you'll solve your issue.