- Home /
Other
same methods in different scripts
Hi, I will be thankfull if you could suggest something on desing-patterns or whatever I need. The thing is I want to use exactly same method but in different scripts. Most answers are like; "create interface/abstract and extend it...". But as I know, these design methods are for "the same purposes, but with slightly differences", like ; you have 2 animals, both have method "voice()" but one is a bird sound and other one is dog sound, so at the end, I create two different instances that has different voice method, and when I write dog.voice, it use dog's voice method and bla bla. But my case is not such detailed. I wanna use exactly same method in my scripts but do not want to write that code part twice.
Here this is my one script has method Move()
public class CubeController : MonoBehaviour
{
private float startX;
private float lastX;
private float distanceX;
private float moveValueX;
bool canMove;
private void Awake()
{
canMove = true;
}
void Update()
{
MoveCube();
}
private void MoveCube()
{
if (canMove)
{
Move();
}
else if (!transform.gameObject.CompareTag("stopped"))
{
Debug.Log("STOP!");
}
}
private void Move()
{
transform.Translate(transform.forward * 5 * Time.deltaTime, Space.World);
if (Input.GetMouseButtonDown(0))
{
startX = Input.mousePosition.x;
}
else if (Input.GetMouseButton(0))
{
lastX = Input.mousePosition.x;
distanceX = lastX - startX;
moveValueX = (distanceX / Screen.width) * 50;
transform.position = new Vector3(Mathf.Clamp(transform.position.x + moveValueX, -5, 5), transform.position.y, transform.position.z);
startX = lastX;
}
}
private void OnTriggerEnter(Collider other)
{
if (other.transform.gameObject.CompareTag("obstacle"))
{
Debug.Log("hitted!");
canMove = false;
transform.gameObject.tag = "stopped";
}
other.transform.gameObject.tag = "none";
}
}
and here this is another script that has method Move()
public class PlayerController : Player
{
private float startX;
private float lastX;
private float distanceX;
private float moveValueX;
void Update()
{
Move();
}
private void Move()
{
transform.Translate(transform.forward * 5 * Time.deltaTime, Space.World);
if (Input.GetMouseButtonDown(0))
{
startX = Input.mousePosition.x;
}
else if (Input.GetMouseButton(0))
{
lastX = Input.mousePosition.x;
distanceX = lastX - startX;
moveValueX = (distanceX / Screen.width) * 50;
transform.position = new Vector3(Mathf.Clamp(transform.position.x + moveValueX, -5, 5), transform.position.y, transform.position.z);
startX = lastX;
}
}
}
Hi there, u could use a singletoon and make reference at the script you want to re-use
public static CubeController instance;
Awake(){
if(instance != null){
instance = this;
else Destroy(gameObject);
}
and then go to your PlayerController script and write
CubeController cubeControl;
Start(){
cubeControl = CubeController.instance;
in this way you can call any method you have in the CubeController
FixedUpdate(){
cubeControl.Move();
}
Thanks for reply but I heard that using singleton is not a good practice, so I try to avoid using it :(
You need to create a public class that contains all of the functions you plan to use within multiple scripts. Create a new script (for this example I'm calling it PublicFunctions). The move function can be adjusted however you need, this one calls for a transform, a direction, and a float.
public class PublicFunctions
{
public void Move(Transform transform, Vector3 direction, float speed)
{
transform.Translate(direction * speed);
}
}
To use the function, you have to create a reference to the class where the function is contained in whatever script you are using, like this:
public class YourScript : MonoBehaviour
{
PublicFunctions publicFunctions;
void Awake()
{
if (!publicFunctions)
{
publicFunctions = new PublicFunctions();
}
}
}
Then you can call the Move function from anywhere in your script:
publicFunctions.Move(YourTransform, YourDirection, YourSpeed);
You can just define a secondary class that does not inherit Monobehaviour and have that class be a member of both CubeController and PlayerController
For example;
class MoveHandler {
public void Move() {
// ...
}
}
and then inside of CubeController
class CubeController : MonoBehaviour {
MoveHandler moveHandler;
void Awake() {
moveHandler = new MoveHandler();
}
void Update() {
moveHandler.Move();
}
}
and likewise for PlayerController. Then you are welcome to use inheritance as you see fit (to implement other types of MoveHandlers. If you don't want/need to do that you can mark the class as static. Finally, if you mark the class as Serializable then you can edit properties in the inspector and will not need to construct it in the Awake method.
Edit: totally did not see all of the replies with the same answer :D
Hi thank you for your reply:) but I couldnt understand the part "if you mark the class as Serializable then you can edit properties in the inspector and will not need to construct it in the Awake method." And I want to know, could you explain it in more detail? :) For example I know that if i write [serializablefield] to the beginning of a property, I can edit its value from inspector. Or if i write [System.Serializable] to the beginning of a class, then i can edit its whole properties etc. But I couldnt understand the way of "no need to construct it in the Awake method".
If a class isn't marked as serializable then it will need to be constructed. Ie;
class MoveHandler {
public void Move() {
// ...
}
}
When used in
class CubeController : MonoBehaviour {
MoveHandler moveHandler;
void Update() {
moveHandler.Move();
}
}
will not show up in the inspector and will require
void Awake() {
moveHandler = new MoveHandler();
}
to be implemented for CubeController. However, if you mark it as serializable. Ie;
[System.Serializable]
class MoveHandler {
public float speed;
public void Move() {
// ...
}
}
then you will not need to construct it inside the Awake method of CubeController. Additionally, speed will show up in the inspector.