Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 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 TheShadyColombian · Oct 14, 2016 at 02:20 AM · renderingspritesdesigntiled

Making a repeating chain of Sprites

I want a make a dynamic chain of sprites, where I take one sprite and unity repeats it between two points (represented by the vector3 positions of two empties). Here's a gif I created in Blender which represents the behaviour I want:

Gfycat.com Link

Comment
Add comment · Show 2
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
avatar image ElijahShadbolt · Oct 14, 2016 at 05:04 AM 0
Share

Have you tried figuring it out for yourself? It's much better to at least have a go at making it, since you might get it right, and you'll learn loads. If you have already tried, we might be able to help you out if you share your code.

avatar image TheShadyColombian ElijahShadbolt · Oct 15, 2016 at 04:24 PM 0
Share

I've tried a few things but I always get stuck at the positioning of the chain links.

What I got so far is to get the distance between the two points and use that to deter$$anonymous$$e the number of chain links. Then, I would use Vector3.lerp , but I don't know what value to give the lerp function

Also, I know I should be doing object pooling to decrease the use of the garbage collector, but I also don't know how to deter$$anonymous$$e which links should be deleted and which ones to re-position.

Here's the current script (it's a terrible mess):

         if (UpdateChain) {
 
             RoundedDistance = $$anonymous$$athf.RoundToInt (Vector3.Distance (transform.position, ConnectTo.position) * 100);
 
             for (int i = 0; i < ChainInstances.Count; i ++) {
 
                 DestroyImmediate (ChainInstances [i]);
 
             }
 
             ChainInstances = new List<GameObject> ();
 
             for (int i = 0; i < RoundedDistance/100; i++) {
                 
                 ChainInstances.Add (Instantiate (ChainPrefab) as GameObject);
 
                 ChainInstances [i].transform.position = Vector3.Lerp (
                     transform.position,
                     ConnectTo.position,
                     (float)i/((float) RoundedDistance)
                 );
 
             }
 
         }

1 Reply

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

Answer by ElijahShadbolt · Oct 16, 2016 at 06:03 AM

The 'LineRenderer' component can be used to make a repeating texture like the one you described, and it always faces the camera. Note that its Material must be a Particle Shader, which means the texture may have transparency where it should be opaque.

  • Add a LineRenderer to the first GameObject

  • set its UseWorldSpace to true

  • Create a new Material

  • Set its Shader to Particles/Additive (LineRenderers only work with Particle shaders)

  • Set your texture (i.e. chain link sprite) as its Particle Texture

  • Set this Material as the LineRenderer's first Material

  • Add the new SpriteLine script below to the GameObject with the LineRenderer

  • Set the second GameObject as its ConnectTo

And you're good to go!

If you want the line to overlap the ConnectTo point instead of stopping before it, change Mathf.FloorToInt to Mathf.CeilToInt.

'Sprite Scale' is how long each sprite should be. If you want to change the width of the sprite, change both the 'Start Width' and 'End Width' of the LineRenderer's 'Parameters' block.

SpriteLine.cs

 using UnityEngine;
 
 public class SpriteLine : MonoBehaviour
 {
     public Transform ConnectTo;
     public bool UpdateChain = true;
     public float spriteScale = 1f;
 
     void Update()
     {
         LineRenderer renderer = GetComponent<LineRenderer>();
         if (renderer != null)
         {
             if (ConnectTo != null)
             {
                 if (UpdateChain)
                 {
                     int spriteCount = Mathf.FloorToInt(Vector3.Distance(ConnectTo.position, transform.position) / spriteScale);
 
                     Vector3[] positions = new Vector3[] {
                     transform.position,
                     (ConnectTo.position - transform.position).normalized * spriteScale * spriteCount
                 };
 
                     renderer.SetVertexCount(positions.Length);
                     renderer.SetPositions(positions);
 
                     if (renderer.material != null)
                         renderer.material.mainTextureScale = new Vector2(spriteScale * spriteCount, 1);
                     else
                         Debug.LogError(name + "'s Line Renderer has no material!");
                 }
             }
             else
             {
                 renderer.SetVertexCount(0);
             }
         }
         else
         {
             Debug.Log(name + " has no LineRenderer component!");
         }
     }
 }

Comment
Add comment · Show 13 · 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
avatar image ElijahShadbolt · Oct 16, 2016 at 07:26 AM 1
Share

If you do not want to use a LineRenderer, you could take this approach, where you make a $$anonymous$$esh from scratch. With this you can use any type of $$anonymous$$aterial shader.

  • Add the below script to an empty GameObject

  • Create a different GameObject with $$anonymous$$eshFilter and $$anonymous$$eshRenderer components

  • $$anonymous$$ake sure the $$anonymous$$eshFilter's $$anonymous$$esh is set to 'none'

  • Set this new GameObject as the SpriteLine3's 'Sprite Renderer' object.

avatar image ElijahShadbolt · Oct 16, 2016 at 07:29 AM 1
Share

SpriteLine3.cs

 using UnityEngine;
 
 public class SpriteLine3 : $$anonymous$$onoBehaviour
 {
     public Transform ConnectTo;
     public bool UpdateChain = true;
     public Vector2 spriteScale = new Vector2(1f, 1f);
 
     public GameObject spriteRenderer; // must have $$anonymous$$eshFilter and $$anonymous$$eshRenderer components
 
     void Update()
     {
         $$anonymous$$eshFilter filter = spriteRenderer.GetComponent<$$anonymous$$eshFilter>();
         Renderer renderer = spriteRenderer.GetComponent<Renderer>();
 
         if (filter != null && renderer != null)
         {
             if (ConnectTo != null)
             {
                 if (UpdateChain)
                 {
                     int spriteCount = $$anonymous$$athf.FloorToInt(Vector3.Distance(ConnectTo.position, transform.position) / spriteScale.y); // or CeilToInt or RoundToInt
 
                     if (spriteCount > 0)
                     {
                         renderer.enabled = true;
 
                         // move the renderer to this point
                         spriteRenderer.transform.position = transform.position;
 
                         Vector3 toTarget = ConnectTo.position - transform.position,
                             toCameraFrom$$anonymous$$id = Camera.main.transform.position - (toTarget / 2);
                         
                         // rotate to have the mesh face the camera
                         // if any of the vectors are Vector3.zero, just set rotation to default
                         spriteRenderer.transform.rotation = (toTarget.sqr$$anonymous$$agnitude > 0.001f && toCameraFrom$$anonymous$$id.sqr$$anonymous$$agnitude > 0.001f) ?
                             Quaternion.LookRotation(toTarget, toCameraFrom$$anonymous$$id) : Quaternion.identity;
 
                         float length = spriteScale.y * spriteCount; // distance to point where sprites stop
                         float width = spriteScale.x / 2;
 
avatar image ElijahShadbolt · Oct 16, 2016 at 07:29 AM 1
Share
                         // create the mesh
                         Vector3[] vertices = new Vector3[] {
                             new Vector3(-width, 0, 0),
                             new Vector3(-width, 0, length),
                             new Vector3(width, 0, length),
 
                             new Vector3(width, 0, length),
                             new Vector3(width, 0, 0),
                             new Vector3(-width, 0, 0),
                         };
                         int[] triangles = new int[]
                         {
                             0, 1, 2,
                             3, 4, 5,
                         };
                         Vector2[] uvs = new Vector2[]
                         {
                             new Vector2(0, 0),
                             new Vector2(1, 0),
                             new Vector2(1, 1),
                             
                             new Vector2(1, 1),
                             new Vector2(0, 1),
                             new Vector2(0, 0),
                         };
 
                         if (filter.mesh == null)
                             filter.mesh = new $$anonymous$$esh();
 
                         $$anonymous$$esh mesh = filter.mesh;
                         mesh.name = "Sprite Line $$anonymous$$esh";
                         mesh.vertices = vertices;
                         mesh.uv = uvs;
                         mesh.triangles = triangles;
 
                         mesh.RecalculateBounds();
                         mesh.RecalculateNormals();
 
                         // scale the texture
                         if (renderer.material != null)
                             renderer.material.mainTextureScale = new Vector2(length, 1);
                         else
                             Debug.LogError(name + "'s $$anonymous$$esh Renderer has no material!");
                     }
                     else
                     {
                         renderer.enabled = false;
                     }
                 }
             }
             else
             {
                 renderer.enabled = false;
             }
         }
         else
         {
             if (filter == null)
                 Debug.Log(name + " has no $$anonymous$$esh Filter component!");
             if (renderer == null)
                 Debug.Log(name + " has no $$anonymous$$esh Renderer component!");
         }
     }
 }
avatar image TheShadyColombian ElijahShadbolt · Oct 16, 2016 at 05:41 PM 0
Share

Wow! This is very useful! I only have one problem right now. It only shows one instance of the sprite, and makes the rest transparent. However, is seems like the actual mesh generation is on point, just not the UV mapping.

Particles>Additive or Unlit>Transparent alt text

Standard Shader>Transparent: alt text

(Also the sprite rotation is off but I'll fix that later )

screen-shot-2016-10-16-at-13710-pm.png (134.5 kB)
screen-shot-2016-10-16-at-13638-pm.png (100.5 kB)
avatar image ElijahShadbolt · Oct 16, 2016 at 06:26 PM 1
Share

Go to the sprite texture in your assets, and make sure its 'Wrap $$anonymous$$ode' is set to Repeat ins$$anonymous$$d of Clamp.

You can rotate the sprite by using different UVs.

Beneath Vector2 spriteScale = new Vector2(1f, 1f); add these lines. This lets you choose the sprite direction in the inspector (you would want Bottom To Top)

     public enum TextureDirection { leftToRight, bottomToTop }
     public TextureDirection spriteDirection;

Replace the code that creates the uvs array with these lines. This checks if it is left to right, and if not it does bottom to top.

                         Vector2[] uvs = spriteDirection == TextureDirection.leftToRight ?
                             new Vector2[]
                             {
                             new Vector2(0, 0),
                             new Vector2(1, 0),
                             new Vector2(1, 1),
                             
                             new Vector2(1, 1),
                             new Vector2(0, 1),
                             new Vector2(0, 0),
                         } : 
                         new Vector2[] // bottomToTop
                         {
                             new Vector2(0, 1),
                             new Vector2(0, 0),
                             new Vector2(1, 0),
 
                             new Vector2(1, 0),
                             new Vector2(1, 1),
                             new Vector2(0, 1),
                         };

And where you scale the texture by setting renderer.material.mainTextureScale, use this ins$$anonymous$$d.

 renderer.material.mainTextureScale = spriteDirection == TextureDirection.leftToRight ? new Vector2(spriteCount, 1) : new Vector2(1, spriteCount);
avatar image TheShadyColombian ElijahShadbolt · Oct 16, 2016 at 07:03 PM 0
Share

Excellent! The looping works. There's only one more thing, if you don't $$anonymous$$d. The "Sprite Scale" variable doesn't work properly. Only the X scale works, but the Y only offsets it sorta.

avatar image ElijahShadbolt TheShadyColombian · Oct 16, 2016 at 07:39 PM 0
Share

Oh yeah, when setting the material's mainTextureScale to a new Vector2, change length to spriteCount.

(I also edited the line in the previous comment)

Show more comments

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

63 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 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 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

2D Graphics Quality 1 Answer

Anti Aliasing and Sprites on Intel HD Graphics 0 Answers

How to make a sprite that change its texture when you go behind it? 0 Answers

How to improve performance with 10,000s of GameObjects? 4 Answers

Eges from other sprites around it 0 Answers


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