Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by shopguy · Sep 10, 2014 at 06:12 AM · guiscrollviewgui.matrix

GUI ScrollView doesn't work with GUI.matrix

I'm using this test code:

 Vector2 scrollVector;
 void OnGUI()
 {
     int DesignedForWidth = 800;
     int DesignedForHeight = 480;
     float xs = Screen.width / (float)DesignedForWidth;
     float ys = Screen.height / (float)DesignedForHeight;
     GUI.matrix = Matrix4x4.TRS(Vector3.zero,  Quaternion.AngleAxis(0, new Vector3(0, 1, 0)), new Vector3(xs, ys, 1));
     Debug.Log(xs + "," + ys + "," + Screen.width + "," + Screen.height);

     GUILayout.BeginHorizontal(GUI.skin.box);
     scrollVector = GUILayout.BeginScrollView(scrollVector, GUILayout.Width(800), GUILayout.Height(480));

     for (int x = 0; x < 30; x++)
         GUILayout.Label("test" + x);

     GUILayout.EndScrollView();
     GUILayout.EndHorizontal();
 }

Which produces these results when I resize the game area in the editor. The top image is 800x480 and the bottom image is 400x240. I was expecting the scroll view to fill the game window regardless of the window height. I want to use something like this to display a list of high scores with Facebook profile pictures next to each item in list.

alt text

As you can hopefully see in the image above, the ScrollView scrollbar stays on the right side, but the box part of the ScrollView is half of the expected width. Seems like maybe there is a bug that is scaling this area twice?

I'm using Unity 4.3.4f1 (I tried to upgrade but it broke several of my existing games so not an easy option). This is a 2D project.

untitled.png (22.7 kB)
Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by shopguy · Sep 21, 2014 at 08:23 PM

The more I worked with it, I found that GUI.ScrollView just wasn't very good, and I think an actual "scrollbar" (thumb, track, etc) is pretty "old school" and/or business application like, not so much "cool" for games. So I created this class that you can attach to any Transform to allow the user to scroll it by dragging the mouse or finger.

This is for 2D games, but could probably be adapted/modified for 3D:

Example usage:

  1. Place an empty game object (Object A)

  2. Add a BoxCollider2D to Object A and adjust the size to cover whatever part of screen you want your scrollable area to cover (you can skip this step, don't add collider, if you want it to cover the entire screen)

  3. Add another empty game object (Object B) as child of Object A

  4. Add this script to Object B

  5. Add your list items as children of Object B

At this point you can play/run your game and see how it works. You will need to adjust some of the public variables that the script exposes based on your games needs. I find it best to adjust these while playing, then make note of the values that work best and re-apply them after you stop game.

 using UnityEngine;
 using System.Collections;
 
 [RequireComponent(typeof(Transform))]
 public class Scroller : MonoBehaviour
 {
     // Set to min X/Y position you want to allow for the transform this script is attached to.
     public float MinScroll = 0;
 
     // Set to max X/Y position you want to allow for the transform this script is attached to.
     public float MaxScroll = 100;
 
     // Set the amount of bounce.  Use 0 to disable bounce.  Higher number will make bounce more obvious.
     public float BounceAmount = 5;
 
     // Direction of scroll.  You can change this at any time, but you'll probably want to reposition the
     //  transform manually if you do, to make sure it isn't already scrolled in one direction.
     public enum Directions { Vertical, Horizontal }
     public Directions Direction = Directions.Vertical;
 
     // Set a collider if you want to limit the area that input is tracked in.  If none set, input will be tracked everywhere.
     public Collider2D Target;
 
     // Higher number makes the "fling to scroll" slow down faster (more friction), set to 0 to make it scroll without slowing
     //  down (until end of list), or set to negative to make it speed up as it scrolls.
     public float Friction = 100;
 
     // Depending on your camera size (game unit to screen size relationship), you may need to adjust these to get "fling to move"
     //  to work well.
     public float MinVelocityRecalcMovementAmount = 1;
     public float VelocitySpeed = 1;
 
     // Internal variables used for state tracking, do not modify.
     Vector3 LastMousePos = Vector3.zero;
     Vector3 LastMouseVelocityPos;
     float LastMouseVelocityTime;
     float LastMouseVelocity;
     float BounceStartTime = 0;
     float BounceStart;
     bool TrackMouse = false;
 
     // Just gets/sets the correct X or Y offset based on Direction.
     float Offset
     {
         get
         {
             if (Direction == Directions.Vertical)
                 return transform.localPosition.y;
             return transform.localPosition.x;
         }
         set
         {
             Vector3 v3 = transform.localPosition;
             if (Direction == Directions.Vertical)
                 v3.y = value;
             else
                 v3.x = value;
             transform.localPosition = v3;
         }
     }
 
     // The max scroll value including bounce (i.e.-can scroll beyond max, then it bounces back)
     float BouncedMax
     {
         get
         {
             return MaxScroll + BounceAmount;
         }
     }
 
     // Min scroll value including bounce
     float BouncedMin
     {
         get
         {
             return MinScroll - BounceAmount;
         }
     }
 
     void Update()
     {
         // Translate screen to world -- screen is harder to adjust for because of all of the different screen sizes
         //  we support -- world units are easier/constant, as long as camera size doesn't change.
         Vector3 mousePosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
 
         // If left mouse button was just pressed (or just touched screen)...
         if (Input.GetMouseButtonDown(0))
         {
             // If not within target bounds, we ignore (if no target we don't limit tracking).
             //  Collider2D.bounds.Contains includes the Z axis in the check, but we want to ignore it, so we create a temp
             //  vector using the Z value of the target for our check.
             if (Target != null && !Target.bounds.Contains(new Vector3(mousePosition.x,mousePosition.y,Target.bounds.center.z)))
                 return;
 
             // Set flag, we will track mouse/touch until up.
             TrackMouse = true;
 
             // We force last mouse pos to update so that we don't act like user dragged from
             //  whatever spot they were at last click/touch.
             LastMousePos = mousePosition;
             LastMouseVelocityPos = LastMousePos;
             LastMouseVelocityTime = Time.time;
 
             // Make sure this is cleared
             BounceStartTime = 0;
         }
 
         // If left mouse button is not currently down (and finger not touching screen)...
         if (!Input.GetMouseButton(0))
         {
             // If left mouse button was just released (or finger just lifted)...
             if (Input.GetMouseButtonUp(0))
             {
                 // If they held still for over 300ms before release, clear velocity so we don't scroll.
                 float elapsedTime = Time.time - LastMouseVelocityTime;
                 if (elapsedTime > 0.3f)
                     LastMouseVelocity = 0;
 
                 // Clear flag, no longer tracking mouse.
                 TrackMouse = false;
             }
 
             // We'll calculate a new offset.
             float newOffset = Offset;
 
             // If we have velocity to apply...
             if (LastMouseVelocity != 0)
             {
                 // Scroll based on velocity
                 newOffset += LastMouseVelocity * Time.deltaTime;
                 if (newOffset < BouncedMin)
                 {
                     newOffset = BouncedMin;
                     LastMouseVelocity = 0;
                 }
                 else if (newOffset > BouncedMax)
                 {
                     newOffset = BouncedMax;
                     LastMouseVelocity = 0;
                 }
 
                 // Reduce velocity based on fiction value
                 if (LastMouseVelocity < 0)
                 {
                     LastMouseVelocity += Time.deltaTime * Friction;
                     if (LastMouseVelocity > 0)
                         LastMouseVelocity = 0;
                 }
                 else if (LastMouseVelocity > 0)
                 {
                     LastMouseVelocity -= Time.deltaTime * Friction;
                     if (LastMouseVelocity < 0)
                         LastMouseVelocity = 0;
                 }
             }
 
             // If scrolled beyond non-bounce range we slowly move back within range (bounce).
             if (newOffset < MinScroll)
             {
                 if (BounceStartTime == 0)
                 {
                     BounceStartTime = Time.time;
                     BounceStart = newOffset;
                 }
                 float elapsedTime = Time.time - BounceStartTime;
                 float bouncePerc = elapsedTime / 0.3f;
                 if (bouncePerc > 1)
                     bouncePerc = 1;
                 newOffset = Mathf.Lerp(BounceStart, MinScroll, bouncePerc);
             }
             else if (newOffset > MaxScroll)
             {
                 if (BounceStartTime == 0)
                 {
                     BounceStartTime = Time.time;
                     BounceStart = newOffset;
                 }
                 float elapsedTime = Time.time - BounceStartTime;
                 float bouncePerc = elapsedTime / 0.3f;
                 if (bouncePerc > 1)
                     bouncePerc = 1;
                 newOffset = Mathf.Lerp(BounceStart, MaxScroll, bouncePerc);
             }
 
             // Apply new offset
             Offset = newOffset;
         }
 
         // Otherwise mouse/touch still down...
         else
         {
             // If not tracking mouse, we do nothing.
             if (!TrackMouse)
                 return;
 
             // Calculate amount of mouse/touch travel in direction we care about.
             float scrollAmount;
             if (Direction == Directions.Vertical)
                 scrollAmount = mousePosition.y - LastMousePos.y;
             else
                 scrollAmount = mousePosition.x - LastMousePos.x;
 
             // Scroll by amount of mouse/touch movement, but keep within bounced range.
             float newOffset = Offset;
             newOffset += scrollAmount;
             if (newOffset < BouncedMin)
                 newOffset = BouncedMin;
             else if (newOffset > BouncedMax)
                 newOffset = BouncedMax;
             Offset = newOffset;
 
             // Update last mouse position
             LastMousePos = mousePosition;
 
             // We only update velocity if input has moved more than a set amount...
             if (Direction == Directions.Vertical)
                 scrollAmount = mousePosition.y - LastMouseVelocityPos.y;
             else
                 scrollAmount = mousePosition.x - LastMouseVelocityPos.x;
             if (Mathf.Abs(scrollAmount) > MinVelocityRecalcMovementAmount)
             {
                 float elapsedTime = Time.time - LastMouseVelocityTime;
                 LastMouseVelocity = (scrollAmount / elapsedTime) * VelocitySpeed;
                 LastMouseVelocityPos = LastMousePos;
                 LastMouseVelocityTime = Time.time;
             }
         }
     }
 }




Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

23 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

4.6 GUI Button inside a scrolling Text Box 0 Answers

Why is my scrollview jittering? 1 Answer

How can I combine a Mask with a Scroll Rect to limit the visible content? 2 Answers

Unity update destroyed my Scrollview UI. How can I restore it? 0 Answers

How to dynamically advance Gui ScrollView 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges