Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

1380206 Posts in 65795 Topics- by 58187 Members - Latest Member: rarbgproxys

August 05, 2020, 05:38:03 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityDevLogsJack Move. A cyberpunk JRPG
Pages: 1 ... 13 14 [15]
Print
Author Topic: Jack Move. A cyberpunk JRPG  (Read 37531 times)
empika
Level 1
*



View Profile WWW
« Reply #280 on: August 01, 2020, 12:12:58 AM »

Hey everyone!

Hope you all had a great week. Feeling a bit funny this week, so not as much got done as I'd have liked, but onwards and upwards!

I've started on a new city area, so have been feeling out how it should look and the "rules" around it. It's a very different area from the stuff that I've made so far. Those have all been in various states of being very lived in, and I want to contrast that with having a very clean city, almost sterile. It's the home of Monomind, the big bad corporation, so I want it to feel oppressive and a bit bleak.

Here's some very work in progress shots. They're lacking most of decoration and wandering npcs.



I tried to show the pathway for the player using the blue highlights on the floor. Joe pointed out that I should take this further by also showing what is actually traversable. For example, in the shot above, I had originally used blue flooring under the center building, but now the pillars are ringed in blue to show that you can go underneath.



As mentioned above, I really wanted to have the city be very clean, but currently it's looking a bit too bland and not actually lived in, so this coming week I'll go back in and add some grime and dirt and a few bit's of foliage and things.

The big screen in the middle is a rendertexture with some UI projected on it. Eventually I'll add some nice sprites and animations for the UI elements and things, but for now I just wanted to check it would work as I was expecting.

I've also done a bunch of work on the custom tile mapper, fixing some stuff and adding a couple of new features to help with the workflow.

Firstly, I've been meaning to add flood fill for a long time. I just added a simple recusive thing to swap the sprite out for the clicked on tile, and then check the tiles north, south, east and west and if they match the original then swap their sprite too, then call the same thing on each of those. It doens't handle filling empty tiles yet, but I'll get to that soon Smiley

The next feature I wanted was to be able to ctrl+click on a tile and select the layer that tile is on. Pretty simple but it has sped up my workflow loads! I also discovered a much better way of selecting tiles using a built in unity function (HandleUtility.PickGameObject) which has cascaded out and improved a couple of other tools too (eg right click to select the tile sprite underneath the cursor). Previously I was calculating the grid coordinate of where the mouse clicks, then figuring out which tile to then filter out and select. Silly me!

Consuming mouse clicks has been a bit of a pain, so here's a simple boilerplate you can use to build your own sceneview tools. Hopefully the comments are self explanatory!

https://gist.github.com/empika/dc5b650fb8516c2f9489eae50aac4c1b

Code:
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;

public class SceneViewEditorBoilerplate : ScriptableObject
{
  public const string SVE_IS_ENABLED = "SVE_IS_ENABLED";

    private bool isLeftMouseDragging = false;
    private bool isRightMouseDragging = false;
    private bool isMiddleMouseDragging = false;
    private List<Vector2> mousePositions = new List<Vector2>();
    private GUIStyle layerLabelStyle;

    // Some singleton business so that we only ever have one editor tool initialised at once
    public static SceneViewEditorBoilerplate Instance
    {
        get
        {
            if(instance == null)
            {
              SceneViewEditorBoilerplate[] editor = Resources.FindObjectsOfTypeAll<SceneViewEditorBoilerplate>();

                if(editor != null && editor.Length > 0)
                {
                    instance = editor[0];
                    for(int i = 1; i < editor.Length; i++)
                    {
                        GameObject.DestroyImmediate(editor[i]);
                    }
                }
            }

            return instance;
        }

        set
        {
            instance = value;
        }
    }

    private static SceneViewEditorBoilerplate instance;

  [MenuItem("Tools/My Scene View Editor %#o", false, 2005)]
    public static void InitTool()
    {
        if (instance == null)
        {
            EditorPrefs.SetBool(SVE_IS_ENABLED, true);
            instance = ScriptableObject.CreateInstance<SceneViewEditorBoilerplate>();
            instance.hideFlags = HideFlags.DontSave;
            EditorApplication.delayCall += instance.Initialize;
        }
        else
        {
            CloseTool();
        }

        SceneView.RepaintAll();
    }

    public static void CloseTool()
    {
      foreach(SceneViewEditorBoilerplate editor in Resources.FindObjectsOfTypeAll<SceneViewEditorBoilerplate>())
        editor.Close();

      Tools.current = Tool.Move;
    }

    public void Close()
    {
      removeListeners();
      EditorPrefs.SetBool(SVE_IS_ENABLED, false);
      DestroyImmediate(this);
    }

    public void Initialize()
    {
      Debug.Log("Initializing SceneViewEditor");

      // Set up all our callbacks
        SceneView.duringSceneGui -= OnSceneGUI;
      SceneView.duringSceneGui += OnSceneGUI;

        EditorApplication.update -= Update;
      EditorApplication.update += Update;

      Undo.undoRedoPerformed -= RepaintSceneView;
      Undo.undoRedoPerformed += RepaintSceneView;

      EditorApplication.playModeStateChanged -= playmodeStateChanged;
      EditorApplication.playModeStateChanged += playmodeStateChanged;
      EditorSceneManager.sceneClosing -= sceneClosing;
      EditorSceneManager.sceneClosing += sceneClosing;
      EditorSceneManager.sceneOpened -= sceneOpened;
      EditorSceneManager.sceneOpened += sceneOpened;

      layerLabelStyle = new GUIStyle();
      layerLabelStyle.alignment = TextAnchor.LowerCenter;
      layerLabelStyle.fontSize = 18;
      layerLabelStyle.normal.textColor = Color.green;

      // Set our tool to None... this is only a visual thing in the toolbar
      // See the click handling below on how to actually bypass unity's tools
      Tools.current = Tool.None;
        instance = this;

      Update();           
        RepaintSceneView();
    }

    private void OnDestroy()
    {
      removeListeners();
    }

    private void removeListeners()
    {
      SceneView.duringSceneGui -= OnSceneGUI;
      EditorApplication.update -= Update;
      Undo.undoRedoPerformed -= RepaintSceneView;

      EditorSceneManager.sceneClosing -= sceneClosing;
      EditorSceneManager.sceneOpened -= sceneOpened;
    }

    private void playmodeStateChanged(PlayModeStateChange state)
    {
      if (state == PlayModeStateChange.EnteredEditMode)
      {
        // Do some stuff here. For example I have a bunch of objects in the sceneview that I set to hidden (tile brush etc)
        // I need to respawn those when we are editing
        Update();           
        RepaintSceneView();
      }
      else if (state == PlayModeStateChange.ExitingEditMode)
      {
        // Do some stuff here. For example I have a bunch of objects in the sceneview that I set to hidden (tile brush etc)
        // I need to remove those when we are playing
      }
    }

    private void sceneClosing(Scene scene, bool removingScene)
    {
      OnDestroy();
    }

    private void sceneOpened(Scene scene, OpenSceneMode mode)
    {
      Initialize();
    }

    void RepaintSceneView()
    {
      SceneView.RepaintAll();
    }

    public void Update()
    {
      if (EditorApplication.isPlaying)
      {
        return;
      }

      // Do some updating stuff here if you need to
    }

    public void OnSceneGUI(SceneView sceneView)
    {
      if (EditorApplication.isPlaying)
      {
        return;
      }

      bool isCurrentView = sceneView == SceneView.lastActiveSceneView;

      if (isCurrentView)
      {
        Handles.BeginGUI();
        DrawSceneGUI();
        Handles.EndGUI();
      }

      HandleUtility.Repaint();
    }

    public void DrawSceneGUI()
    {
      Rect screenRect = SceneView.lastActiveSceneView.position;

      GUI.Label(new Rect(screenRect.width / 2, 10, 200, 40), "Scene View Editor", layerLabelStyle);

      // This is kinda like the update in the normal monobehaviours, but for the sceneview
      // The mouse handling gets quite complicated so we just handle them all, all the time
      handleClick(screenRect);
      handleRightClick();
    }

    private void handleClick(Rect screenRect)
    {
      Event e = Event.current;
      if (screenRect.Contains(e.mousePosition))
      {
        // This control id stuff is pretty confusing and i still don't 100% understand it
        // We get a control id from unity, to say we're doing something
        // Don't know why we check GUIUtility.hotControl != 0, but if it is then we want to tell it our
        int controlId = GUIUtility.GetControlID (FocusType.Passive);
        if (e.type == EventType.MouseDown && Event.current.button == 0 && GUIUtility.hotControl != 0)
        {
          GUIUtility.hotControl = controlId;
          // This is the start of the drag, for whatever reason unity's EventType.MouseDrag doesnt quite work
          // how you'd expect so we want to track this ourselves
          isLeftMouseDragging = true;
        }
        else if (e.type == EventType.MouseUp && Event.current.button == 0 && GUIUtility.hotControl == controlId)
        {
          if (mousePositions.Count == 0)
          {
            // We got a click! We're not dragging or anything so just do something normal!
            // ...
            // or we can check for modifiers first...

            if (e.control)
            {
              // we got a ctrl click
            }
            else
            {
              // just a normal click
            }


            // We need to set the hotcontrol to 0 to let unity know we're all done
            GUIUtility.hotControl = 0;
          }

          // We're no longer dragging
          isLeftMouseDragging = false;
          mousePositions.Clear();       

          // This is where we consume the mouse click, so that unity doesnt do it's normal stuff with selecting or moving etc
          e.Use();
          RepaintSceneView();
        }
        else if (e.type == EventType.MouseDrag && Event.current.button == 0 && GUIUtility.hotControl == controlId)
        {
          // Are we dragging... like we set earlier
          if (isLeftMouseDragging)
          {
            // Yes we are, so add this mouse position to the list
            mousePositions.Add(e.mousePosition);

            // We're dragging so we can do stuff here. In my tile map, I create a tile here based on the position.

            // clear those mouse positions
            mousePositions.Clear();

            // This is where we consume the mouse drag, so that unity doesnt do it's normal stuff with selecting or moving etc
            e.Use();
            RepaintSceneView();
          }
        }
      }
    }

    private void handleRightClick()
    {
      Event e = Event.current;
      if (e.type == EventType.MouseDown && Event.current.button == 1)
      {
        isRightMouseDragging = false;
      }
      else if (e.type == EventType.MouseDrag && Event.current.button == 1 && e.command )
      {
        isRightMouseDragging = true;
        // Note that here the command key is pressed and we are dragging, I don't consume the event with e.Use().
        // This is so that can do the normal camera orbit in the scene view, but it requires the command key to be pressed,
        // I want a right click to select the tile in the tile map without affecting the camera at all
      }
      else if (e.type == EventType.MouseDrag && Event.current.button == 1)
      {
        isRightMouseDragging = true;
        // This is where we consume the mouse drag, so that unity doesnt do it's normal stuff with selecting or moving etc
        e.Use();
      }
          else if (e.type == EventType.MouseUp && Event.current.button == 1)
          {
            if (isRightMouseDragging == false)
            {
              // This is just a normal right click
            }

            isRightMouseDragging = false;
          }
        }
    }

I had some issues using middle click, so no idea what's up with that.

Hope that helps someone! Let me know if you have any questions, comments, improvements etc.

Come join the discord for more gifs, screeshots and discussion http://www.soromantic.co.uk/discord

..and please wishlist Jack Move on steam! https://store.steampowered.com/app/1099640/Jack_Move/
Logged

andy wolff
Level 10
*****


-------


View Profile
« Reply #281 on: August 01, 2020, 11:06:46 AM »

The visuals in this game are top notch. Excellent work
Logged

empika
Level 1
*



View Profile WWW
« Reply #282 on: August 02, 2020, 04:16:00 AM »

The visuals in this game are top notch. Excellent work

Thanks Andy!  Kiss
Logged

Pages: 1 ... 13 14 [15]
Print
Jump to:  

Theme orange-lt created by panic