1

Тема: Чому це лайно не працює??

Прів. Є текстурка на весь екран, котра оброблюється скриптом RawImage.
В цього RawImage є uvRect, і якщо змінювати uvRect.y - то текстурка типу зрушується, такий собі offset.
Ну і так, як текстурка повторюється, то за допомогою зміни uvRect.y і за умови, що це текстурка землі, чи травички, створюється уявлення, що це камера рухається вздовж землі.
Тут ще така фігня, що uvRect містить ще змінні height і width. Якщо збільшити height, то текстурка зтискається в стільки-то разів. Якщо height = 1, то для того, аби зсунути текстурку на одне "коло", потрібно змінити uvRect.y з 0 до 1. А якщо height = 8, то для одного циклічного зсуву треба змінювати uvRect.y з 0 до 8.

І от помістив я об'єкта над цією текстуркою, об'єкт - пташка. І потрібно мені, аби ця пташка могла какулькати. Ну і я зробив от так - під дупою пташки з'являється какулька, після чого вона зменшується в 2 рази за 0.5 секунди, а потім вона падає на землю. Ну і зрозуміло, що якщо земля рухається кудись там, то й какулька, що впала на землю, повинна рухатись разом з землею. Але от в чому фігня, какулька - це об'єкт, і в нього своя система координат.

Але я це вирішив дуже просто. Висота екрана == 600. І тут є проста залежність, якщо верх в координатах текстури - це 0, а низ - 8, то в координатах екрана верх - це 0, а низ - це 600. Тобто якщо розділимо 600 на 8, то отримаємо 1 в координатах текстури. Ну і потім можна просто взяти швидкість "руху" текстури і помножити на 600/8, тобто на 75, і отримаємо ту ж саму швидкість, але вже в координатах екрану.
Я так і зробив, і воно працює гарно.

Але потім я захтів зробити приціл. І цей приціл повинен вказувати місце на текстурці, куди впаде какулька.
Для цього мені потрібно з'ясувати, яку відстань пролітає какулька за 0.5 секунди.
І тут я думаю...
Якщо кожен кадр, що продовжується Time.deltaTime, я зсуваю текстуру на speed*Time.deltaTime, то для того, аби порахувати довжину, на котру я зрушую текстурку за 0.5 секунди, потрібно зробити
(0.5/Time.deltatime)*(speed*Time.deltaTime)
тобто спочатку рахуємо кількість кадрів за 0.5 секунди, а потім просто множу speed*Time.deltaTime на це число.
Вірно ж?
І якщо це довжина в координатах текстури, то мені потрібно помножити її на 75, і тоді я переведу її в координати екрану. Ага?

І тоді виходе така формула (0.5*speed*75), тому що Time.deltaTime скорочується.

Але воно шось не працює.... Працює лише от така формула speed*75. Без 0.5.
Чому воно таке?

скрін, якщо тре

Прихований текст

http://не-дійсний-домен/qCsMP/df07aabf39.png

От вам всі скрипти, що я юзаю

Оце головний, тут я створюю какульки і позиціоную приціл в методі SetAimPos

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class MovementController : MonoBehaviour {

    public RectTransform trans;
    public float speed, speedRot;
    public Transform ass, aim;

    private Canvas canvas;
    private float canvasHeight, canvasWidth;

    private Vector2 neededPosition;
    private Quaternion neededRotation;
    private GameObject poopPref;
    private Vector2 birdsDirection;
    private Vector2 assDirection;
    private Vector3 oldPosition;

    // Use this for initialization
    void Start () {
        canvas = FindObjectOfType<Canvas>();
        poopPref = Resources.Load("Poop") as GameObject;
        canvasHeight = (canvas.transform as RectTransform).rect.height/2f;
        canvasWidth = (canvas.transform as RectTransform).rect.width/2f;

        neededPosition = trans.localPosition;
        neededRotation = trans.rotation;

        if (speed == 0)
            speed = 1;
        if (speedRot == 0)
            speedRot = 1;

        SetAimPos();
    }
    
    // Update is called once per frame
    void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform, Input.mousePosition, Camera.main, out neededPosition);
            //neededPosition = canvas.transform.TransformPoint(pos);
            Debug.Log("needed pos: " + neededPosition);
            if (neededPosition == (Vector2)oldPosition)
                return;

            Vector2 currPosN = Vector2.up;
            Vector2 needPosN = neededPosition - (Vector2)trans.localPosition;
            needPosN.Normalize();
            float dot = Vector2.Dot(currPosN, needPosN);
            if (dot < 0)
                dot *= -1f;
            float z = 90f - (dot * 90f);
            z *= 0.5f;
            if (needPosN.x > 0)
                z *= -1f;
            neededRotation = Quaternion.Euler(0, 0, z);
        }

        if (trans.position != oldPosition)
        {
            SetAimPos();
        }

        if (trans.position!=(Vector3)neededPosition)
        {
            trans.localPosition = Vector3.MoveTowards(trans.localPosition, neededPosition, Time.deltaTime * speed);
            if(trans.localPosition==(Vector3)neededPosition)
            {
                neededRotation = Quaternion.Euler(0, 0, 0);
            }
        }

        if(trans.rotation!=neededRotation)
        {
            trans.rotation = Quaternion.RotateTowards(trans.rotation, neededRotation, Time.deltaTime * speedRot);
        }

        if(Input.GetKeyDown(KeyCode.Space))
        {
            Vector2 globalPosAss;
            Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(Camera.main, ass.position);
            RectTransformUtility.ScreenPointToLocalPointInRectangle(GroundController.Instance.Ground, screenPoint , Camera.main, out globalPosAss);
            GameObject poop = Instantiate(poopPref, globalPosAss, Quaternion.identity, GroundController.Instance.Ground) as GameObject;
            Transform poopTrans = poop.transform;
            poopTrans.localScale = Vector3.one;
            poopTrans.localPosition = globalPosAss;

            Vector2 globalPosAim;
            Vector2 screenPointAim = RectTransformUtility.WorldToScreenPoint(Camera.main, aim.position);
            RectTransformUtility.ScreenPointToLocalPointInRectangle(GroundController.Instance.Ground, screenPointAim, Camera.main, out globalPosAim);
            PoopController poopController = poop.GetComponent<PoopController>();
            poopController.Empty(globalPosAim);

            GameObject anotherPoop = Instantiate(poopPref, globalPosAim, Quaternion.identity, GroundController.Instance.Ground) as GameObject;
            Transform poopTrans1 = anotherPoop.transform;
           // poopTrans.SetParent(GroundController.Instance.Ground);
            poopTrans1.localScale = Vector3.one;
            poopTrans1.localPosition = globalPosAss;
            PoopController poopController1 = anotherPoop.GetComponent<PoopController>();
            poopController1.SetPos(globalPosAss);
            poopController1.move = true;
            poopController1.GetComponent<Image>().color = Color.red;

            GameObject anotherPoop1 = Instantiate(poopPref, globalPosAim, Quaternion.identity, GroundController.Instance.Ground) as GameObject;
            Transform poopTrans2 = anotherPoop.transform;
            // poopTrans.SetParent(GroundController.Instance.Ground);
            poopTrans2.localScale = Vector3.one;
            poopTrans2.localPosition = globalPosAss;
            PoopController poopController2 = anotherPoop1.GetComponent<PoopController>();
            poopController2.SetPos(globalPosAim);
            poopController2.move = true;
            poopController2.GetComponent<Image>().color = Color.yellow ;
        }
    }

    void SetAimPos()
    {
        Vector2 assScreenPoint = RectTransformUtility.WorldToScreenPoint(Camera.main, ass.position);
        Vector2 assLocalInGround;
        RectTransformUtility.ScreenPointToLocalPointInRectangle(GroundController.Instance.Ground, assScreenPoint, Camera.main, out assLocalInGround);
        Vector2 direction = trans.position - oldPosition;
        Vector2 aimPos = assLocalInGround + (direction.normalized * MultiplyVector2D(MultiplyVector2D(GroundController.Instance.speed,GroundController.Instance.speedOfGround), Vector2.up).y);

        aim.localPosition = aimPos;
        oldPosition = trans.position;
    }

    Vector2 MultiplyVector2D(Vector2 first, Vector2 second)
    {
        return new Vector2(first.x * second.x, first.y * second.y);
    }
}

А тута рухається земля

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using System.Collections.Generic;
using System;
using Random = UnityEngine.Random;

[Serializable]
public class Path
{
    public Vector2 point;
    public bool isFilled;
}

public class GroundController : MonoBehaviour {

    public RawImage ground;
    public Vector2 speed;
    public Vector2 speedOfGround;
    public float height, width;
    public List<Path> humanPaths;

    private Rect rect;
    private GameObject humanPref;
    private RectTransform rootGround;
    private float humanWidth, humanHeigth;
    private float groundWidth;
    private Vector2 oldSpeed;

    private static GroundController instance;

    public static GroundController Instance
    {
        get
        {
            return instance;
        }
    }

    public RectTransform Ground
    {
        get
        {
            return rootGround;
        }
    }

    void Awake()
    {
        if (instance == null)
            instance = this;
    }

    // Use this for initialization
    void Start () {
        rect = ground.uvRect;
        rootGround = ground.rectTransform;
        humanPref = Resources.Load("Human") as GameObject;
        height = rootGround.rect.height;
        width = rootGround.rect.width;
        CalculateSpeedOfGround();
        groundWidth = rootGround.rect.width;

        GameObject tempPref = Instantiate(humanPref);
        humanWidth = (tempPref.transform as RectTransform).rect.width;
        humanHeigth = (tempPref.transform as RectTransform).rect.height;
        Destroy(tempPref);

        float pathWidthF = groundWidth / humanWidth;
        int pathsCount = (int)Mathf.Floor(pathWidthF);
        float rest = groundWidth - pathsCount*humanWidth;

        float newHumanWidth = groundWidth / pathsCount;

       // Debug.Log("newHumanWidth: " + newHumanWidth);

       // Debug.Log("pathWidthF: " + pathWidthF + "  pathsCount: " + pathsCount + " rest: " + rest);

        rest = rest / pathsCount;

        //Debug.Log("rest: " + rest);

        humanPaths = new List<Path>();

        for(int i =0; i<pathsCount; i++)
        {
            Path path = new Path();
            path.point = new Vector2((newHumanWidth / 2f)+(i*(newHumanWidth)) +(-(groundWidth/2f)), (height / 2f) + (humanHeigth / 2f));
            path.isFilled = false;

            humanPaths.Add(path);
        }

        oldSpeed = speed;
    }
    
    void CalculateSpeedOfGround()
    {
        speedOfGround.y = (height / ground.uvRect.height);
        speedOfGround.x = (width / ground.uvRect.width);
    }

    // Update is called once per frame
    void Update () {
         rect.position += (speed * Time.deltaTime);
         ground.uvRect = rect;

        if(oldSpeed!=speed)
        {
            CalculateSpeedOfGround();
        }

        if (Input.GetKeyDown(KeyCode.P))
        {
            var paths = humanPaths.FindAll((v)=> { return v.isFilled == false; });

            if (paths.Count==0)
                return;

            GameObject newHuman = Instantiate(humanPref);
            var hc = newHuman.GetComponent<HumanController>();

            var nhTrans = newHuman.transform as RectTransform;
            nhTrans.SetParent(rootGround);

            var path = paths[Random.Range(0, paths.Count)];
            path.isFilled = true;

            hc.Path = path;

            nhTrans.localPosition = path.point;
            nhTrans.localScale = Vector3.one;
        }
    }
}

А оце скрипт, що висить на какульці

using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using DG.Tweening;

public class PoopController : MonoBehaviour {

    public float timeInAir = 1f;
    public bool move;
    private Transform trans;
    private Vector2 position;
    private float destroyHeight;

    void Start()
    {
        trans = transform;
        destroyHeight = -(GroundController.Instance.height / 2f) - ((transform as RectTransform).rect.height / 2f);
    }

    public void SetPos(Vector2 pos)
    {
        position = pos;
    }

    public void Empty(Vector3 destination)
    {
        //transform.DOLocalMove(destination, timeInAir).SetEase(Ease.Linear);
        transform.DOScale(0.5f, timeInAir).SetEase(Ease.Linear).OnComplete(()=> {
            position = trans.localPosition;
            move = true;
        });
    }

    void Update()
    {
        if(move)
        {
            position.y -= (GroundController.Instance.speedOfGround.y* GroundController.Instance.speed.y * Time.deltaTime);
            trans.localPosition = position;

            if (position.y <= destroyHeight)
            {
                DestroyImmediate(gameObject);
            }
        }
    }
}

2

Re: Чому це лайно не працює??

Можливо підхід до вирішення задачі не вірний.Тому спочатку потрібно чітко сформулювати задачу.

3

Re: Чому це лайно не працює??

лайно не працює, тому що воно лайно?

Подякували: 221VOLT, c3c, ostap34PHP3

4

Re: Чому це лайно не працює??

можливо, тому що... краще б ви взагалі нічо не писали!!!